]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Fix comment in AC DEFINE
[andy/viking.git] / src / viktrwlayer.c
index 0942cdc2581969fcb9d77580e88d6c1ab864c4d1..720ff8fff62ae667b6bef371d5849484509f4d40 100644 (file)
@@ -62,8 +62,6 @@
 #include "vikexttools.h"
 #include "vikexttool_datasources.h"
 #include "ui_util.h"
-#include "vikutils.h"
-
 #include "vikrouting.h"
 
 #include "icons/icons.h"
@@ -180,7 +178,6 @@ struct _VikTrwLayer {
   GdkGC *waypoint_text_gc; GdkColor waypoint_text_color;
   GdkGC *waypoint_bg_gc; GdkColor waypoint_bg_color;
   gboolean wpbgand;
-  GdkFont *waypoint_font;
   VikTrack *current_track; // ATM shared between new tracks and new routes
   guint16 ct_x1, ct_y1, ct_x2, ct_y2;
   gboolean draw_sync_done;
@@ -690,7 +687,7 @@ enum {
 /* 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_post_read ( VikTrwLayer *vtl, GtkWidget *vvp, gboolean from_file );
+static void trw_layer_post_read ( VikTrwLayer *vtl, VikViewport *vvp, gboolean from_file );
 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 );
@@ -918,8 +915,8 @@ typedef struct {
   const gchar *date_str;
   const VikTrack *trk;
   const VikWaypoint *wpt;
-  gpointer *trk_id;
-  gpointer *wpt_id;
+  gpointer trk_id;
+  gpointer wpt_id;
 } date_finder_type;
 
 static gboolean trw_layer_find_date_track ( const gpointer id, const VikTrack *trk, date_finder_type *df )
@@ -1031,7 +1028,7 @@ static void trw_layer_copy_item_cb ( menu_array_sublayer values)
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(values[MA_VTL]);
   gint subtype = GPOINTER_TO_INT (values[MA_SUBTYPE]);
-  gpointer sublayer = values[MA_SUBLAYER_ID];
+  gpointer sublayer = values[MA_SUBLAYER_ID];
   guint8 *data = NULL;
   guint len;
 
@@ -1174,6 +1171,12 @@ static void trw_layer_free_copied_item ( gint subtype, gpointer item )
   }
 }
 
+static void image_cache_free ( VikTrwLayer *vtl )
+{
+  g_list_foreach ( vtl->image_cache->head, (GFunc)cached_pixbuf_free, NULL );
+  g_queue_free ( vtl->image_cache );
+}
+
 static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
 {
   switch ( id )
@@ -1245,12 +1248,17 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara
     case PARAM_IS: if ( data.u != vtl->image_size )
       {
         vtl->image_size = data.u;
-        g_list_foreach ( vtl->image_cache->head, (GFunc) cached_pixbuf_free, NULL );
-        g_queue_free ( vtl->image_cache );
+        image_cache_free ( vtl );
+        vtl->image_cache = g_queue_new ();
+      }
+      break;
+    case PARAM_IA: if ( data.u != vtl->image_alpha )
+      {
+        vtl->image_alpha = data.u;
+        image_cache_free ( vtl );
         vtl->image_cache = g_queue_new ();
       }
       break;
-    case PARAM_IA: vtl->image_alpha = data.u; break;
     case PARAM_ICS: vtl->image_cache_size = data.u;
       while ( vtl->image_cache->length > vtl->image_cache_size ) /* if shrinking cache_size, free pixbuf ASAP */
           cached_pixbuf_free ( g_queue_pop_tail ( vtl->image_cache ) );
@@ -1527,23 +1535,27 @@ static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *v
       // Reuse pl to read the subtype from the data stream
       memcpy(&pl, data+sizeof(gint), sizeof(pl));
 
+      // Also remember to (attempt to) convert each coordinate in case this is pasted into a different drawmode
       if ( pl == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
         VikTrack *trk = vik_track_unmarshall ( data + sizeof_len_and_subtype, 0 );
         gchar *name = g_strdup ( trk->name );
         vik_trw_layer_add_track ( vtl, name, trk );
         g_free ( name );
+        vik_track_convert (trk, vtl->coord_mode);
       }
       if ( pl == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) {
         VikWaypoint *wp = vik_waypoint_unmarshall ( data + sizeof_len_and_subtype, 0 );
         gchar *name = g_strdup ( wp->name );
         vik_trw_layer_add_waypoint ( vtl, name, wp );
         g_free ( name );
+        waypoint_convert (NULL, wp, &vtl->coord_mode);
       }
       if ( pl == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
         VikTrack *trk = vik_track_unmarshall ( data + sizeof_len_and_subtype, 0 );
         gchar *name = g_strdup ( trk->name );
         vik_trw_layer_add_route ( vtl, name, trk );
         g_free ( name );
+        vik_track_convert (trk, vtl->coord_mode);
       }
     }
     consumed_length += tlm_size + sizeof_len_and_subtype;
@@ -1619,6 +1631,7 @@ static VikTrwLayer* trw_layer_new1 ( VikViewport *vvp )
   rv->metadata = vik_trw_metadata_new ();
   rv->draw_sync_done = TRUE;
   rv->draw_sync_do = TRUE;
+  rv->coord_mode = VIK_COORD_LATLON;
   // Everything else is 0, FALSE or NULL
 
   return rv;
@@ -1667,8 +1680,7 @@ static void trw_layer_free ( VikTrwLayer *trwlayer )
   if ( trwlayer->tracks_analysis_dialog != NULL )
     gtk_widget_destroy ( GTK_WIDGET(trwlayer->tracks_analysis_dialog) );
 
-  g_list_foreach ( trwlayer->image_cache->head, (GFunc) cached_pixbuf_free, NULL );
-  g_queue_free ( trwlayer->image_cache );
+  image_cache_free ( trwlayer );
 }
 
 static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp, gboolean highlight )
@@ -2176,7 +2188,7 @@ static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct Dr
          // Still need to process points to ensure 'stops' are drawn if required
          if ( drawstops && drawpoints && ! draw_track_outline && list->next &&
               (VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length) )
-           vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
+           vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, VIK_TRW_LAYER_TRACK_GC_STOP), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
 
          goto skip;
        }
@@ -2391,6 +2403,10 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct
           }
           cp->image = g_strdup ( image );
 
+          // Apply alpha setting to the image before the pixbuf gets stored in the cache
+          if ( dp->vtl->image_alpha != 255 )
+            cp->pixbuf = ui_pixbuf_set_alpha ( cp->pixbuf, dp->vtl->image_alpha );
+
           /* needed so 'click picture' tool knows how big the pic is; we don't
            * store it in cp because they may have been freed already. */
           wp->image_width = gdk_pixbuf_get_width ( cp->pixbuf );
@@ -2424,10 +2440,7 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct
                                          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
-            vik_viewport_draw_pixbuf_with_alpha ( dp->vp, pixbuf, dp->vtl->image_alpha, 0, 0, x - (w/2), y - (h/2), w, h );
+          vik_viewport_draw_pixbuf ( dp->vp, pixbuf, 0, 0, x - (w/2), y - (h/2), w, h );
         }
         return; /* if failed to draw picture, default to drawing regular waypoint (below) */
       }
@@ -2810,7 +2823,7 @@ static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *
     vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), vtl->waypoints_visible );
   }
 
-  trw_layer_verify_thumbnails ( vtl, NULL );
+  trw_layer_verify_thumbnails ( vtl );
 
   trw_layer_sort_all ( vtl );
 }
@@ -3071,7 +3084,7 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g
        if ( tr->trackpoints && vik_track_get_tp_first(tr)->has_timestamp ) {
          // %x     The preferred date representation for the current locale without the time.
          strftime (time_buf1, sizeof(time_buf1), "%x: ", gmtime(&(vik_track_get_tp_first(tr)->timestamp)));
-         time_t dur = vik_track_get_duration ( tr );
+         time_t dur = vik_track_get_duration ( tr, TRUE );
          if ( dur > 0 )
            g_snprintf ( time_buf2, sizeof(time_buf2), _("- %d:%02d hrs:mins"), (int)(dur/3600), (int)round(dur/60.0)%60 );
        }
@@ -3308,7 +3321,7 @@ GHashTable *vik_trw_layer_get_routes_iters ( VikTrwLayer *vtl )
 
 GHashTable *vik_trw_layer_get_waypoints_iters ( VikTrwLayer *vtl )
 {
-  return vtl->waypoints;
+  return vtl->waypoints_iters;
 }
 
 gboolean vik_trw_layer_is_empty ( VikTrwLayer *vtl )
@@ -3435,51 +3448,7 @@ static void trw_layer_centerize ( menu_array_layer values )
 
 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, TRUE );
-
-  /* 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 );
-  }
+  vu_zoom_to_show_latlons ( vtl->coord_mode, vvp, maxmin );
 }
 
 gboolean vik_trw_layer_auto_set_view ( VikTrwLayer *vtl, VikViewport *vvp )
@@ -3616,13 +3585,13 @@ static void trw_layer_goto_wp ( menu_array_layer values )
 
   GtkWidget *label, *entry;
   label = gtk_label_new(_("Waypoint Name:"));
-  entry = gtk_entry_new();
+  entry = ui_entry_new ( NULL, GTK_ENTRY_ICON_SECONDARY );
 
   gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), label, FALSE, FALSE, 0);
   gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), entry, FALSE, FALSE, 0);
-  gtk_widget_show_all ( label );
-  gtk_widget_show_all ( entry );
-
+  gtk_widget_show_all ( dia );
+  // 'ok' when press return in the entry
+  g_signal_connect_swapped ( entry, "activate", G_CALLBACK(a_dialog_response_accept), dia );
   gtk_dialog_set_default_response ( GTK_DIALOG(dia), GTK_RESPONSE_ACCEPT );
 
   while ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_ACCEPT )
@@ -3644,7 +3613,7 @@ static void trw_layer_goto_wp ( menu_array_layer values )
       udata.uuid = NULL;
 
       // Hmmm, want key of it
-      gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+      gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
 
       if ( wpf && udata.uuid ) {
         GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
@@ -3849,7 +3818,7 @@ static void trw_layer_acquire_geotagged_cb ( menu_array_layer values )
 
   // Reverify thumbnails as they may have changed
   vtl->has_verified_thumbnails = FALSE;
-  trw_layer_verify_thumbnails ( vtl, NULL );
+  trw_layer_verify_thumbnails ( vtl );
 }
 #endif
 
@@ -4210,10 +4179,12 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer
   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 );
+  if ( a_babel_available () ) {
+    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 );
+  }
 
   if ( have_geojson_export ) {
     item = gtk_menu_item_new_with_mnemonic ( _("Export as GEO_JSON...") );
@@ -4222,10 +4193,12 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer
     gtk_widget_show ( item );
   }
 
-  item = gtk_menu_item_new_with_mnemonic ( _("Export via GPSbabel...") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_babel), pass_along );
-  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
-  gtk_widget_show ( item );
+  if ( a_babel_available () ) {
+    item = gtk_menu_item_new_with_mnemonic ( _("Export via GPSbabel...") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_babel), pass_along );
+    gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+    gtk_widget_show ( item );
+  }
 
   gchar* external1 = g_strdup_printf ( _("Open with External Program_1: %s"), a_vik_get_external_gpx_program_1() );
   item = gtk_menu_item_new_with_mnemonic ( external1 );
@@ -4347,11 +4320,13 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer
   gtk_widget_show ( item );
 #endif
 
-  item = gtk_menu_item_new_with_mnemonic ( _("From _File...") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_file_cb), pass_along );
-  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
-  gtk_widget_set_tooltip_text (item, _("Import File With GPS_Babel..."));
-  gtk_widget_show ( item );
+  if ( a_babel_available () ) {
+    item = gtk_menu_item_new_with_mnemonic ( _("From _File...") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_file_cb), pass_along );
+    gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+    gtk_widget_set_tooltip_text (item, _("Import File With GPS_Babel..."));
+    gtk_widget_show ( item );
+  }
 
   vik_ext_tool_datasources_add_menu_items_to_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), GTK_MENU (acquire_submenu) );
 
@@ -4618,7 +4593,19 @@ gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type,
     }
     // If found a name already in use try adding 1 to it and we try again
     if ( id ) {
-      gchar *new_newname = g_strdup_printf("%s#%d", name, i);
+      const gchar *corename = newname;
+      gint newi = i;
+      // If name is already of the form text#N
+      //  set name to text and i to N+1
+      gchar **tokens = g_regex_split_simple ( "#(\\d+)", newname, G_REGEX_CASELESS, 0 );
+      if ( tokens ) {
+        corename = tokens[0];
+        if ( tokens[1] ) {
+          newi = atoi ( tokens[1] ) + 1;
+        }
+      }
+      gchar *new_newname = g_strdup_printf("%s#%d", corename, newi);
+      g_strfreev ( tokens );
       g_free(newname);
       newname = new_newname;
       i++;
@@ -4643,10 +4630,12 @@ void vik_trw_layer_filein_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t
     // enforce end of current track equal to start of tr
     VikTrackpoint *cur_end = vik_track_get_tp_last ( vtl->current_track );
     VikTrackpoint *new_start = vik_track_get_tp_first ( tr );
-    if ( ! vik_coord_equals ( &cur_end->coord, &new_start->coord ) ) {
-        vik_track_add_trackpoint ( vtl->current_track,
-                                   vik_trackpoint_copy ( cur_end ),
-                                   FALSE );
+    if ( cur_end && new_start ) {
+      if ( ! vik_coord_equals ( &cur_end->coord, &new_start->coord ) ) {
+          vik_track_add_trackpoint ( vtl->current_track,
+                                     vik_trackpoint_copy ( cur_end ),
+                                     FALSE );
+      }
     }
 
     vik_track_steal_and_append_trackpoints ( vtl->current_track, tr );
@@ -4799,7 +4788,7 @@ gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, VikTrack *trk )
     udata.uuid = NULL;
 
     // Hmmm, want key of it
-    gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+    gpointer trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
 
     if ( trkf && udata.uuid ) {
       /* could be current_tp, so we have to check */
@@ -4847,7 +4836,7 @@ gboolean vik_trw_layer_delete_route ( VikTrwLayer *vtl, VikTrack *trk )
     udata.uuid = NULL;
 
     // Hmmm, want key of it
-    gpointer *trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+    gpointer trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
 
     if ( trkf && udata.uuid ) {
       /* could be current_tp, so we have to check */
@@ -4891,7 +4880,7 @@ static gboolean trw_layer_delete_waypoint ( VikTrwLayer *vtl, VikWaypoint *wp )
     udata.uuid = NULL;
 
     // Hmmm, want key of it
-    gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+    gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
 
     if ( wpf && udata.uuid ) {
       GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
@@ -4943,7 +4932,7 @@ static gboolean trw_layer_delete_waypoint_by_name ( VikTrwLayer *vtl, const gcha
   udata.uuid = NULL;
 
   // Hmmm, want key of it
-  gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid_by_name, (gpointer) &udata );
+  gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid_by_name, (gpointer) &udata );
 
   vik_waypoint_free (udata.wp);
 
@@ -4984,7 +4973,7 @@ static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *
   udata.uuid = NULL;
 
   // Hmmm, want key of it
-  gpointer *trkf = g_hash_table_find ( ht_tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
+  gpointer trkf = g_hash_table_find ( ht_tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
 
   vik_track_free (udata.trk);
 
@@ -5015,9 +5004,10 @@ void vik_trw_layer_delete_all_routes ( VikTrwLayer *vtl )
 
   g_hash_table_foreach(vtl->routes_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
   g_hash_table_remove_all(vtl->routes_iters);
-  g_hash_table_remove_all(vtl->routes);
 
-  vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+  if ( g_hash_table_size (vtl->routes) > 0 )
+    vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+  g_hash_table_remove_all(vtl->routes);
 
   vik_layer_emit_update ( VIK_LAYER(vtl) );
 }
@@ -5032,9 +5022,10 @@ void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
 
   g_hash_table_foreach(vtl->tracks_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
   g_hash_table_remove_all(vtl->tracks_iters);
-  g_hash_table_remove_all(vtl->tracks);
 
-  vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+  if ( g_hash_table_size (vtl->tracks) > 0 )
+    vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+  g_hash_table_remove_all(vtl->tracks);
 
   vik_layer_emit_update ( VIK_LAYER(vtl) );
 }
@@ -5049,9 +5040,10 @@ void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
 
   g_hash_table_foreach(vtl->waypoints_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
   g_hash_table_remove_all(vtl->waypoints_iters);
-  g_hash_table_remove_all(vtl->waypoints);
 
-  vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+  if ( g_hash_table_size (vtl->waypoints) > 0 )
+    vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+  g_hash_table_remove_all(vtl->waypoints);
 
   vik_layer_emit_update ( VIK_LAYER(vtl) );
 }
@@ -5152,7 +5144,7 @@ void trw_layer_waypoint_rename ( VikTrwLayer *vtl, VikWaypoint *wp, const gchar
   udataU.uuid = NULL;
 
   // Need key of it for treeview update
-  gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
+  gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
 
   if ( wpf && udataU.uuid ) {
     GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid );
@@ -5175,7 +5167,7 @@ void trw_layer_waypoint_reset_icon ( VikTrwLayer *vtl, VikWaypoint *wp )
   udataU.uuid = NULL;
 
   // Need key of it for treeview update
-  gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
+  gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
 
   if ( wpf && udataU.uuid ) {
     GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid );
@@ -5262,7 +5254,7 @@ void trw_layer_update_treeview ( VikTrwLayer *vtl, VikTrack *trk )
   udata.trk  = trk;
   udata.uuid = NULL;
 
-  gpointer *trkf = NULL;
+  gpointer trkf = NULL;
   if ( trk->is_route )
     trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
   else
@@ -6368,7 +6360,7 @@ static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subt
       udata.uuid = NULL;
 
       // Also need id of newly created track
-      gpointer *trkf;
+      gpointer trkf;
       if ( tr->is_route )
          trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
       else
@@ -7100,7 +7092,7 @@ static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vl
     udataU.uuid = NULL;
 
     // Need want key of it for treeview update
-    gpointer *trkf = g_hash_table_find ( track_table, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+    gpointer trkf = g_hash_table_find ( track_table, (GHRFunc) trw_layer_track_find_uuid, &udataU );
 
     if ( trkf && udataU.uuid ) {
 
@@ -7118,6 +7110,7 @@ static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vl
           vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), vtl->track_sort_order );
       }
     }
+    g_free ( newname );
 
     // Start trying to find same names again...
     track_names = NULL;
@@ -7376,6 +7369,8 @@ static void vik_trw_layer_uniquify_waypoints ( VikTrwLayer *vtl, VikLayersPanel
 
     trw_layer_waypoint_rename ( vtl, waypoint, newname );
 
+    g_free (newname);
+
     // Start trying to find same names again...
     waypoint_names = NULL;
     g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_sorted_wp_id_by_name_list, &waypoint_names );
@@ -7888,7 +7883,7 @@ static void trw_layer_google_route_webpage ( menu_array_sublayer values )
 {
   VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(values[MA_VTL])->routes, values[MA_SUBLAYER_ID] );
   if ( tr ) {
-    gchar *escaped = uri_escape ( tr->comment );
+    gchar *escaped = g_uri_escape_string ( tr->comment, NULL, TRUE );
     gchar *webpage = g_strdup_printf("http://maps.google.com/maps?f=q&hl=en&q=%s", escaped );
     open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(values[MA_VTL])), webpage);
     g_free ( escaped );
@@ -9075,7 +9070,7 @@ typedef struct {
   gint x, y;
   gint closest_x, closest_y;
   gboolean draw_images;
-  gpointer *closest_wp_id;
+  gpointer closest_wp_id;
   VikWaypoint *closest_wp;
   VikViewport *vvp;
 } WPSearchParams;
@@ -9470,7 +9465,7 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve
       udataU.trk  = track;
       udataU.uuid = NULL;
 
-      gpointer *trkf;
+      gpointer trkf;
       if ( track->is_route )
         trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udataU );
       else
@@ -9513,7 +9508,7 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve
       udata.wp   = waypoint;
       udata.uuid = NULL;
 
-      gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+      gpointer wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
 
       if ( wpf && udata.uuid ) {
         GtkTreeIter *iter = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
@@ -9541,10 +9536,8 @@ static gboolean tool_sync_done = TRUE;
 static gboolean tool_sync(gpointer data)
 {
   VikViewport *vvp = data;
-  gdk_threads_enter();
   vik_viewport_sync(vvp);
   tool_sync_done = TRUE;
-  gdk_threads_leave();
   return FALSE;
 }
 
@@ -9786,13 +9779,11 @@ static gboolean draw_sync ( gpointer data )
   //  normally because another update has taken precedent such as panning the display
   //   which means this pixmap is no longer valid
   if ( ds->vtl->draw_sync_do ) {
-    gdk_threads_enter();
     gdk_draw_drawable (ds->drawable,
                        ds->gc,
                        ds->pixmap,
                        0, 0, 0, 0, -1, -1);
     ds->vtl->draw_sync_done = TRUE;
-    gdk_threads_leave();
   }
   g_free ( ds );
   return FALSE;
@@ -10595,7 +10586,7 @@ static void thumbnail_create_thread_free ( thumbnail_create_thread_data *tctd )
   g_free ( tctd );
 }
 
-void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
+void trw_layer_verify_thumbnails ( VikTrwLayer *vtl )
 {
   if ( ! vtl->has_verified_thumbnails )
   {
@@ -10735,7 +10726,7 @@ static void trw_layer_calculate_bounds_track ( gpointer id, VikTrack *trk )
   vik_track_calculate_bounds ( trk );
 }
 
-static void trw_layer_calculate_bounds_tracks ( VikTrwLayer *vtl )
+void trw_layer_calculate_bounds_tracks ( VikTrwLayer *vtl )
 {
   g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_calculate_bounds_track, NULL );
   g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_calculate_bounds_track, NULL );
@@ -10825,10 +10816,10 @@ static time_t trw_layer_get_timestamp ( VikTrwLayer *vtl )
   return timestamp_waypoints;
 }
 
-static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vvp, gboolean from_file )
+static void trw_layer_post_read ( VikTrwLayer *vtl, VikViewport *vvp, gboolean from_file )
 {
   if ( VIK_LAYER(vtl)->realized )
-    trw_layer_verify_thumbnails ( vtl, vvp );
+    trw_layer_verify_thumbnails ( vtl );
   trw_layer_track_alloc_colors ( vtl );
 
   trw_layer_calculate_bounds_waypoints ( vtl );
@@ -11153,7 +11144,7 @@ static gint highest_wp_number_name_to_number(const gchar *name) {
 
 static void highest_wp_number_reset(VikTrwLayer *vtl)
 {
-  vtl->highest_wp_number = -1;
+  vtl->highest_wp_number = 0;
 }
 
 static void highest_wp_number_add_wp(VikTrwLayer *vtl, const gchar *new_wp_name)