]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Add Terraserver
[andy/viking.git] / src / viktrwlayer.c
index 89737105e539e6c85557f8b413cda7a7a603a2c9..9fb218ed5059e281175b995af8529c5020c84358 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "viking.h"
 #include "vikmapslayer.h"
 
 #include "viking.h"
 #include "vikmapslayer.h"
-#include "viktrwlayer_pixmap.h"
 #include "viktrwlayer_tpwin.h"
 #include "viktrwlayer_propwin.h"
 #include "garminsymbols.h"
 #include "viktrwlayer_tpwin.h"
 #include "viktrwlayer_propwin.h"
 #include "garminsymbols.h"
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <ctype.h>
 #include <ctype.h>
-#include <unistd.h>
 
 #include <gdk/gdkkeysyms.h>
 
 #include <gdk/gdkkeysyms.h>
+#include <glib.h>
+#include <glib/gstdio.h>
 #include <glib/gi18n.h>
 
 /* Relax some dependencies */
 #include <glib/gi18n.h>
 
 /* Relax some dependencies */
@@ -64,7 +65,7 @@ static gboolean return_true (gpointer a, gpointer b, gpointer c) { return TRUE;
 static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); }
 #endif
 
 static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); }
 #endif
 
-#define GOOGLE_DIRECTIONS_STRING "(wget -O - \"http://maps.google.com/maps?q=%f,%f to %f,%f&output=js\" 2>/dev/null)"
+#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js"
 #define VIK_TRW_LAYER_TRACK_GC 13
 #define VIK_TRW_LAYER_TRACK_GC_RATES 10
 #define VIK_TRW_LAYER_TRACK_GC_MIN 0
 #define VIK_TRW_LAYER_TRACK_GC 13
 #define VIK_TRW_LAYER_TRACK_GC_RATES 10
 #define VIK_TRW_LAYER_TRACK_GC_MIN 0
@@ -253,19 +254,19 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl );
 
 static gpointer tool_edit_trackpoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 
 static gpointer tool_edit_trackpoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
-static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
+static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data );
 static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gpointer tool_edit_waypoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gpointer tool_edit_waypoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
-static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
+static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data );
 static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data );
 static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
-static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
+static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ); 
 static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); 
 static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
 static 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 );
@@ -273,8 +274,6 @@ static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
 
 
 static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
 
 
-static gboolean uppercase_exists_in_hash ( GHashTable *hash, const gchar *str );
-
 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 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 );
@@ -296,30 +295,30 @@ static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_na
 
 static VikToolInterface trw_layer_tools[] = {
   { N_("Create Waypoint"), (VikToolConstructorFunc) tool_new_waypoint_create,    NULL, NULL, NULL, 
 
 static VikToolInterface trw_layer_tools[] = {
   { N_("Create Waypoint"), (VikToolConstructorFunc) tool_new_waypoint_create,    NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_new_waypoint_click,    NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp },
+    (VikToolMouseFunc) tool_new_waypoint_click,    NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf },
 
   { N_("Create Track"),    (VikToolConstructorFunc) tool_new_track_create,       NULL, NULL, NULL, 
 
   { N_("Create Track"),    (VikToolConstructorFunc) tool_new_track_create,       NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_new_track_click, (VikToolMouseFunc) tool_new_track_move, NULL,
-    (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr },
+    (VikToolMouseFunc) tool_new_track_click, (VikToolMouseMoveFunc) tool_new_track_move, NULL,
+    (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
 
   { N_("Begin Track"),    (VikToolConstructorFunc) tool_begin_track_create,       NULL, NULL, NULL, 
 
   { N_("Begin Track"),    (VikToolConstructorFunc) tool_begin_track_create,       NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_begin_track_click,       NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr },
+    (VikToolMouseFunc) tool_begin_track_click,       NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
 
   { N_("Edit Waypoint"),   (VikToolConstructorFunc) tool_edit_waypoint_create,   NULL, NULL, NULL, 
     (VikToolMouseFunc) tool_edit_waypoint_click,   
 
   { N_("Edit Waypoint"),   (VikToolConstructorFunc) tool_edit_waypoint_create,   NULL, NULL, NULL, 
     (VikToolMouseFunc) tool_edit_waypoint_click,   
-    (VikToolMouseFunc) tool_edit_waypoint_move,
-    (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp },
+    (VikToolMouseMoveFunc) tool_edit_waypoint_move,
+    (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
 
   { N_("Edit Trackpoint"), (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, 
     (VikToolMouseFunc) tool_edit_trackpoint_click,
 
   { N_("Edit Trackpoint"), (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, 
     (VikToolMouseFunc) tool_edit_trackpoint_click,
-    (VikToolMouseFunc) tool_edit_trackpoint_move,
-    (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr },
+    (VikToolMouseMoveFunc) tool_edit_trackpoint_move,
+    (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
 
   { N_("Show Picture"),    (VikToolConstructorFunc) tool_show_picture_create,    NULL, NULL, NULL, 
 
   { 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 },
+    (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,
 
   { 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 },
+    (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_iscissors_pixbuf },
 };
 enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
 
 };
 enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
 
@@ -392,7 +391,7 @@ enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PAR
 
 VikLayerInterface vik_trw_layer_interface = {
   "TrackWaypoint",
 
 VikLayerInterface vik_trw_layer_interface = {
   "TrackWaypoint",
-  &trwlayer_pixbuf,
+  &viktrwlayer_pixbuf,
 
   trw_layer_tools,
   sizeof(trw_layer_tools) / sizeof(VikToolInterface),
 
   trw_layer_tools,
   sizeof(trw_layer_tools) / sizeof(VikToolInterface),
@@ -480,7 +479,7 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay
   
   pass_along[0] = vtl;
   pass_along[1] = NULL;
   
   pass_along[0] = vtl;
   pass_along[1] = NULL;
-  pass_along[2] = (gpointer) subtype;
+  pass_along[2] = GINT_TO_POINTER (subtype);
   pass_along[3] = sublayer;
   pass_along[4] = NULL;
 
   pass_along[3] = sublayer;
   pass_along[4] = NULL;
 
@@ -490,7 +489,7 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay
 static void trw_layer_copy_item_cb( gpointer pass_along[5])
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
 static void trw_layer_copy_item_cb( gpointer pass_along[5])
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
-  gint subtype = (gint)pass_along[2];
+  gint subtype = GPOINTER_TO_INT (pass_along[2]);
   gpointer * sublayer = pass_along[3];
   guint8 *data = NULL;
   guint len;
   gpointer * sublayer = pass_along[3];
   guint8 *data = NULL;
   guint len;
@@ -677,6 +676,7 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
     a_gpx_write_file(vtl, f);
     vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
     fclose(f);
     a_gpx_write_file(vtl, f);
     vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
     fclose(f);
+    f = NULL;
     g_file_get_contents(tmpname, (void *)&dd, (void *)&dl, NULL);
     *len = sizeof(pl) + pl + dl;
     *data = g_malloc(*len);
     g_file_get_contents(tmpname, (void *)&dd, (void *)&dl, NULL);
     *len = sizeof(pl) + pl + dl;
     *data = g_malloc(*len);
@@ -686,7 +686,7 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
     
     g_free(pd);
     g_free(dd);
     
     g_free(pd);
     g_free(dd);
-    remove(tmpname);
+    g_remove(tmpname);
     g_free(tmpname);
   }
 }
     g_free(tmpname);
   }
 }
@@ -712,7 +712,8 @@ static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport *
   rewind(f);
   a_gpx_read_file(rv, f);
   fclose(f);
   rewind(f);
   a_gpx_read_file(rv, f);
   fclose(f);
-  remove(tmpname);
+  f = NULL;
+  g_remove(tmpname);
   g_free(tmpname);
   return rv;
 }
   g_free(tmpname);
   return rv;
 }
@@ -726,6 +727,33 @@ static GList * str_array_to_glist(gchar* data[])
   return(g_list_reverse(gl));
 }
 
   return(g_list_reverse(gl));
 }
 
+static gboolean strcase_equal(gconstpointer s1, gconstpointer s2)
+{
+  return (strcasecmp(s1, s2) == 0);
+}
+
+static guint strcase_hash(gconstpointer v)
+{
+  /* 31 bit hash function */
+  int i;
+  const gchar *t = v;
+  gchar s[128];   /* malloc is too slow for reading big files */
+  gchar *p = s;
+
+  for (i = 0; (i < (sizeof(s)- 1)) && t[i]; i++)
+      p[i] = toupper(t[i]);
+  p[i] = '\0';
+
+  p = s;
+  guint32 h = *p;
+  if (h) {
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+  }
+
+  return h;  
+}
+
 VikTrwLayer *vik_trw_layer_new ( gint drawmode )
 {
   if (trw_layer_params[PARAM_DM].widget_data == NULL)
 VikTrwLayer *vik_trw_layer_new ( gint drawmode )
 {
   if (trw_layer_params[PARAM_DM].widget_data == NULL)
@@ -736,10 +764,10 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
   VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) );
   vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW );
 
   VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) );
   vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW );
 
-  rv->waypoints = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_waypoint_free );
+  rv->waypoints = g_hash_table_new_full ( strcase_hash, strcase_equal, g_free, (GDestroyNotify) vik_waypoint_free );
   rv->tracks = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_track_free );
   rv->tracks_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
   rv->tracks = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_track_free );
   rv->tracks_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
-  rv->waypoints_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
+  rv->waypoints_iters = g_hash_table_new_full ( strcase_hash, strcase_equal, NULL, g_free );
 
   /* TODO: constants at top */
   rv->waypoints_visible = rv->tracks_visible = TRUE;
 
   /* TODO: constants at top */
   rv->waypoints_visible = rv->tracks_visible = TRUE;
@@ -1306,7 +1334,7 @@ static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pas
   GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
 
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
   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, (gint) pass_along[4], NULL, TRUE, TRUE );
+  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 );
 #endif
 #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 );
 #endif
@@ -1322,7 +1350,7 @@ static void trw_layer_realize_waypoint ( gchar *name, VikWaypoint *wp, gpointer
 {
   GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
 {
   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, (gint) pass_along[4], NULL, TRUE, TRUE );
+  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 );
 #endif
 #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 );
 #endif
@@ -1478,7 +1506,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type )
   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
   {
     fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) );
   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
   {
     fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) );
-    if ( access ( fn, F_OK ) != 0 )
+    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 );
     {
       gtk_widget_hide ( file_selector );
       failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type );
@@ -1486,7 +1514,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type )
     }
     else
     {
     }
     else
     {
-      if ( a_dialog_overwrite ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
+      if ( a_dialog_overwrite ( 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 );
       {
         gtk_widget_hide ( file_selector );
         failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type );
@@ -1714,21 +1742,6 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
  
 }
 
  
 }
 
-static gboolean uppercase_exists_in_hash ( GHashTable *hash, const gchar *str )
-{
-  gchar *upp = g_strdup ( str );
-  gboolean rv;
-  char *tmp = upp;
-  while  ( *tmp )
-  {
-    *tmp = toupper(*tmp);
-    tmp++;
-  }
-  rv = g_hash_table_lookup ( hash, upp ) ? TRUE : FALSE;
-  g_free (upp);
-  return rv;
-}
-
 /* to be called whenever a track has been deleted or may have been changed. */
 void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name )
 {
 /* to be called whenever a track has been deleted or may have been changed. */
 void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name )
 {
@@ -1930,7 +1943,7 @@ static void trw_layer_delete_item ( gpointer pass_along[5] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   gboolean was_visible = FALSE;
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   gboolean was_visible = FALSE;
-  if ( (gint) pass_along[2] == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
+  if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
     was_visible = vik_trw_layer_delete_waypoint ( vtl, (gchar *) pass_along[3] );
   }
   {
     was_visible = vik_trw_layer_delete_waypoint ( vtl, (gchar *) pass_along[3] );
   }
@@ -1946,7 +1959,7 @@ static void trw_layer_delete_item ( gpointer pass_along[5] )
 static void trw_layer_properties_item ( gpointer pass_along[5] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
 static void trw_layer_properties_item ( gpointer pass_along[5] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
-  if ( (gint) pass_along[2] == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
+  if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
     VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
     if ( wp )
   {
     VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
     if ( wp )
@@ -2005,12 +2018,30 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] )
   VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
 
   vtl->current_track = track;
   VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
 
   vtl->current_track = track;
-  vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK );
+  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) );
 }
 
 
   if ( track->trackpoints )
     goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) );
 }
 
+/**
+ * extend a track using magic scissors
+ */
+static void trw_layer_extend_track_end_ms ( 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;
+
+  if ( track->trackpoints )
+    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &last_coord) ;
+
+}
+
 static void trw_layer_apply_dem_data ( gpointer pass_along[6] )
 {
   /* TODO: check & warn if no DEM data, or no applicable DEM data. */
 static void trw_layer_apply_dem_data ( gpointer pass_along[6] )
 {
   /* TODO: check & warn if no DEM data, or no applicable DEM data. */
@@ -2044,7 +2075,7 @@ static void find_nearby_track(gpointer key, gpointer value, gpointer user_data)
 
   GList **nearby_tracks = ((gpointer *)user_data)[0];
   GList *orig_track = ((gpointer *)user_data)[1];
 
   GList **nearby_tracks = ((gpointer *)user_data)[0];
   GList *orig_track = ((gpointer *)user_data)[1];
-  guint thr = (guint)((gpointer *)user_data)[2];
+  guint thr = GPOINTER_TO_UINT (((gpointer *)user_data)[2]);
 
   /* outline: 
    * detect reasons for not merging, and return
 
   /* outline: 
    * detect reasons for not merging, and return
@@ -2146,7 +2177,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
     /*    g_print("Original track times: %d and %d\n", t1, t2);  */
     params[0] = &nearby_tracks;
     params[1] = trps;
     /*    g_print("Original track times: %d and %d\n", t1, t2);  */
     params[0] = &nearby_tracks;
     params[1] = trps;
-    params[2] = (gpointer)thr;
+    params[2] = GUINT_TO_POINTER (thr);
 
     /* get a list of adjacent-in-time tracks */
     g_hash_table_foreach(vtl->tracks, find_nearby_track, (gpointer)params);
 
     /* get a list of adjacent-in-time tracks */
     g_hash_table_foreach(vtl->tracks, find_nearby_track, (gpointer)params);
@@ -2285,17 +2316,18 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar
 {
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
 {
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
-    int i;
     gchar *rv;
     VikWaypoint *wp;
 
     gchar *rv;
     VikWaypoint *wp;
 
-    if ( strcasecmp ( newname, sublayer ) == 0 )
+    if (strcmp(newname, sublayer) == 0 )
       return NULL;
 
       return NULL;
 
-    if ( uppercase_exists_in_hash ( l->waypoints, newname ) )
-    {
-      a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Waypoint Already Exists") );
-      return NULL;
+    if (strcasecmp(newname, sublayer)) { /* Not just changing case */
+      if (g_hash_table_lookup( l->waypoints, newname))
+      {
+        a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Waypoint Already Exists") );
+        return NULL;
+      }
     }
 
     iter = g_hash_table_lookup ( l->waypoints_iters, sublayer );
     }
 
     iter = g_hash_table_lookup ( l->waypoints_iters, sublayer );
@@ -2306,8 +2338,6 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar
     g_hash_table_remove ( l->waypoints, sublayer );
 
     rv = g_strdup(newname);
     g_hash_table_remove ( l->waypoints, sublayer );
 
     rv = g_strdup(newname);
-    for ( i = strlen(rv) - 1; i >= 0; i-- )
-      rv[i] = toupper(rv[i]);
 
     vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
 
 
     vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
 
@@ -2325,19 +2355,20 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar
   }
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
   }
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
-    int i;
     gchar *rv;
     VikTrack *tr;
     GtkTreeIter *iter;
     gchar *orig_key;
 
     gchar *rv;
     VikTrack *tr;
     GtkTreeIter *iter;
     gchar *orig_key;
 
-    if ( strcasecmp ( newname, sublayer ) == 0 )
+    if (strcmp(newname, sublayer) == 0)
       return NULL;
 
       return NULL;
 
-    if ( uppercase_exists_in_hash ( l->tracks, newname ) )
-    {
-      a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") );
-      return NULL;
+    if (strcasecmp(newname, sublayer)) { /* Not just changing case */
+      if (g_hash_table_lookup( l->waypoints, newname))
+      {
+        a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") );
+        return NULL;
+      }
     }
 
     g_hash_table_lookup_extended ( l->tracks, sublayer, (void *)&orig_key, (void *)&tr );
     }
 
     g_hash_table_lookup_extended ( l->tracks, sublayer, (void *)&orig_key, (void *)&tr );
@@ -2347,8 +2378,6 @@ const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar
     g_hash_table_steal ( l->tracks_iters, sublayer );
 
     rv = g_strdup(newname);
     g_hash_table_steal ( l->tracks_iters, sublayer );
 
     rv = g_strdup(newname);
-    for ( i = strlen(rv) - 1; i >= 0; i-- )
-      rv[i] = toupper(rv[i]);
 
     vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
 
 
     vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
 
@@ -2419,7 +2448,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
   pass_along[0] = l;
   pass_along[1] = vlp;
 
   pass_along[0] = l;
   pass_along[1] = vlp;
-  pass_along[2] = (gpointer) subtype;
+  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[3] = sublayer;
   staticiter = *iter; /* will exist after function has ended */
   pass_along[4] = &staticiter;
@@ -2517,11 +2546,16 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
     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_menu_item_new_with_label ( _("Extend track end") );
     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 );
 
     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 );
+    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") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
 #ifdef VIK_CONFIG_OPENSTREETMAP
     item = gtk_menu_item_new_with_label ( _("Upload to OSM") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
@@ -2531,13 +2565,13 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
     if ( is_valid_google_route ( l, (gchar *) sublayer ) )
     {
 
     if ( is_valid_google_route ( l, (gchar *) sublayer ) )
     {
-      item = gtk_menu_item_new_with_label ( "View Google Directions" );
+      item = gtk_menu_item_new_with_label ( _("View Google Directions") );
       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 );
     }
 
       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" );
+    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 );
     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 );
@@ -2955,7 +2989,7 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
   return FALSE;
 }
 
   return FALSE;
 }
 
-static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data )
+static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data )
 {
   tool_ed_t *t = data;
   VikViewport *vvp = t->vvp;
 {
   tool_ed_t *t = data;
   VikViewport *vvp = t->vvp;
@@ -3080,7 +3114,7 @@ static gboolean ct_sync ( gpointer passalong )
   return FALSE;
 }
 
   return FALSE;
 }
 
-static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp )
 {
   /* if we haven't sync'ed yet, we don't have time to do more. */
   if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
 {
   /* if we haven't sync'ed yet, we don't have time to do more. */
   if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
@@ -3298,7 +3332,7 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
   return FALSE;
 }
 
   return FALSE;
 }
 
-static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data )
+static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data )
 {
   tool_ed_t *t = data;
   VikViewport *vvp = t->vvp;
 {
   tool_ed_t *t = data;
   VikViewport *vvp = t->vvp;
@@ -3399,11 +3433,12 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev
   }
   else if ( vtl->magic_scissors_started || (event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track) ) {
     struct LatLon start, end;
   }
   else if ( vtl->magic_scissors_started || (event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track) ) {
     struct LatLon start, end;
-    gchar *cmd;
+    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 ( &(tmp), &end );
 
     vik_coord_to_latlon ( &(vtl->magic_scissors_coord), &start );
     vik_coord_to_latlon ( &(tmp), &end );
-    cmd = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, start.lat, start.lon, end.lat, end.lon );
     vtl->magic_scissors_coord = tmp; /* for continuations */
 
     /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */
     vtl->magic_scissors_coord = tmp; /* for continuations */
 
     /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */
@@ -3414,8 +3449,13 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev
       vtl->magic_scissors_started = FALSE;
     }
 
       vtl->magic_scissors_started = FALSE;
     }
 
-    a_babel_convert_from_shellcommand ( vtl, cmd, "google", NULL, NULL );
-    g_free ( cmd );
+    url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING,
+                          g_ascii_dtostr (startlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lat),
+                          g_ascii_dtostr (startlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lon),
+                          g_ascii_dtostr (endlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lat),
+                          g_ascii_dtostr (endlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lon));
+    a_babel_convert_from_url ( vtl, url, "google", NULL, NULL );
+    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 ) {
 
     /* 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 ) {