]> err.no Git - mapper/blobdiff - src/route.c
Parse directly but update informations in callbacks only if we got a sentence that...
[mapper] / src / route.c
index dfb61aff8720a9ded0f1c15f974476088202715f..32fafbbd60ee3419902d7e42eadeab95a7f52bd3 100644 (file)
@@ -1,7 +1,5 @@
 #include <config.h>
 
-#define _GNU_SOURCE
-
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include "latlon.h"
 #include "map.h"
 #include "map-download.h"
+#include "iap.h"
+
+#include "help.h"
+
+#define DISTANCE_SQUARED(a, b) \
+   ((guint64)((((gint64)(b).unitx)-(a).unitx)*(((gint64)(b).unitx)-(a).unitx))\
+  + (guint64)((((gint64)(b).unity)-(a).unity)*(((gint64)(b).unity)-(a).unity)))
 
-void route_find_nearest_point();
+void route_find_nearest_point(void);
 void cancel_autoroute(gboolean temporary);
+void route_show_distance_to_last(void);
+void route_set_destination_from_last(void);
 
 typedef struct _OriginToggleInfo OriginToggleInfo;
 struct _OriginToggleInfo {
@@ -70,6 +77,7 @@ if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
        route_find_nearest_point();
        map_force_redraw();
 }
+_dest.valid=FALSE;
 gtk_widget_destroy(confirm);
 }
 
@@ -79,16 +87,16 @@ route_open_file(void)
 gchar *buffer;
 gint size;
 
-if (open_file(&buffer, NULL, &size, &_route_dir_uri, NULL, GTK_FILE_CHOOSER_ACTION_OPEN)) {
+if (file_open_get_contents(&_route_dir_uri, &buffer, &size)) {
        /* If auto is enabled, append the route, otherwise replace it. */
        if (parse_gpx(&_route, buffer, size, _autoroute_data.enabled ? 0 : 1)) {
                cancel_autoroute(FALSE);
 
+               MACRO_BANNER_SHOW_INFO(_window, _("Route Opened"));
                /* Find the nearest route point, if we're connected. */
                route_find_nearest_point();
-
                map_force_redraw();
-               MACRO_BANNER_SHOW_INFO(_window, _("Route Opened"));
+               route_set_destination_from_last();
                return TRUE;
        } else {
                popup_error(_window, _("Error parsing GPX file."));
@@ -99,6 +107,9 @@ if (open_file(&buffer, NULL, &size, &_route_dir_uri, NULL, GTK_FILE_CHOOSER_ACTI
 return FALSE;
 }
 
+/**
+ * Ask user to save route
+ */
 gboolean
 route_save(void)
 {
@@ -116,45 +127,42 @@ if (file_save(&_route_dir_uri, &_route_dir_uri, &handle)) {
 return FALSE;
 }
 
-gboolean 
-origin_type_selected(GtkWidget * toggle, OriginToggleInfo * oti)
+/**
+ *
+ */
+static gboolean 
+origin_type_selected_cb(GtkWidget * toggle, OriginToggleInfo * oti)
 {
+if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) {
+       if (toggle == oti->rad_use_gps) {
+               gchar buffer[80];
+               gchar strlat[32];
+               gchar strlon[32];
+               g_ascii_formatd(strlat, 32, "%.06f", _gps->data.lat);
+               g_ascii_formatd(strlon, 32, "%.06f", _gps->data.lon);
+               g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
+               gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
+       } else if (toggle == oti->rad_use_route) {
+               gchar buffer[80];
+               gchar strlat[32];
+               gchar strlon[32];
+               Point *p;
+               gdouble lat, lon;
 
-       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) {
-               if (toggle == oti->rad_use_gps) {
-                       gchar buffer[80];
-                       gchar strlat[32];
-                       gchar strlon[32];
-                       g_ascii_formatd(strlat, 32, "%.06f", _gps.lat);
-                       g_ascii_formatd(strlon, 32, "%.06f", _gps.lon);
-                       snprintf(buffer, sizeof(buffer), "%s, %s", strlat,
-                                strlon);
-                       gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
-               } else if (toggle == oti->rad_use_route) {
-                       gchar buffer[80];
-                       gchar strlat[32];
-                       gchar strlon[32];
-                       Point *p;
-                       gfloat lat, lon;
-
-                       /* Use last non-zero route point. */
-                       for (p = _route.tail; !p->unity; p--) {
-                       }
-
-                       unit2latlon(p->unitx, p->unity, lat, lon);
-                       g_ascii_formatd(strlat, 32, "%.06f", lat);
-                       g_ascii_formatd(strlon, 32, "%.06f", lon);
-                       snprintf(buffer, sizeof(buffer), "%s, %s", strlat,
-                                strlon);
-                       gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
+               /* Use last non-zero route point. */
+               for (p = _route.tail; !p->unity; p--) {
                }
 
-               gtk_widget_set_sensitive(oti->txt_from,
-                                        toggle == oti->rad_use_text);
-               gtk_widget_set_sensitive(oti->chk_auto,
-                                        toggle == oti->rad_use_gps);
+               unit2latlon(p->unitx, p->unity, lat, lon);
+               g_ascii_formatd(strlat, 32, "%.06f", lat);
+               g_ascii_formatd(strlon, 32, "%.06f", lon);
+               g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
+               gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
        }
-       return TRUE;
+       gtk_widget_set_sensitive(oti->txt_from, toggle == oti->rad_use_text);
+       gtk_widget_set_sensitive(oti->chk_auto, toggle == oti->rad_use_gps);
+}
+return TRUE;
 }
 
 /**
@@ -210,20 +218,17 @@ auto_route_dl_idle()
 {
 gchar latstr[32], lonstr[32], *latlonstr;
 
-g_ascii_dtostr(latstr, 32, _gps.lat);
-g_ascii_dtostr(lonstr, 32, _gps.lon);
+g_ascii_dtostr(latstr, 32, _gps->data.lat);
+g_ascii_dtostr(lonstr, 32, _gps->data.lon);
 latlonstr = g_strdup_printf("%s,%s", latstr, lonstr);
 _autoroute_data.src_str =
     g_strdup_printf(_route_dl_url, latlonstr, _autoroute_data.dest);
 g_free(latlonstr);
 
 MACRO_CURL_EASY_INIT(_autoroute_data.curl_easy);
-curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_URL,
-                _autoroute_data.src_str);
-curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEFUNCTION,
-                route_dl_cb_read);
-curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA,
-                &_autoroute_data.rdl_data);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_URL, _autoroute_data.src_str);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEFUNCTION, route_dl_cb_read);
+curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA, &_autoroute_data.rdl_data);
 if (!_curl_multi) {
        /* Initialize CURL. */
        _curl_multi = curl_multi_init();
@@ -231,11 +236,7 @@ if (!_curl_multi) {
 }
 curl_multi_add_handle(_curl_multi, _autoroute_data.curl_easy);
 
-#ifdef WITH_OSSO
 if (iap_is_connected() && !_curl_sid)
-#else
-if (!_curl_sid)
-#endif
        _curl_sid = g_timeout_add(100, (GSourceFunc) map_download_timeout, NULL);
 
 _autoroute_data.in_progress = TRUE;
@@ -265,9 +266,7 @@ OriginToggleInfo oti;
 GtkEntryCompletion *from_comp;
 GtkEntryCompletion *to_comp;
 
-#ifdef WITH_OSSO
 iap_connect();
-#endif
 
 dialog = gtk_dialog_new_with_buttons(_("Download Route"),
                             GTK_WINDOW(_window),
@@ -276,10 +275,7 @@ dialog = gtk_dialog_new_with_buttons(_("Download Route"),
                             GTK_STOCK_CANCEL,
                             GTK_RESPONSE_REJECT, NULL);
 
-#ifdef WITH_OSSO
-/* Enable the help button. */
-ossohelp_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE, _osso);
-#endif
+help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE);
 
 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
           table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0);
@@ -342,11 +338,11 @@ gtk_table_attach(GTK_TABLE(table),
 gtk_entry_set_completion(GTK_ENTRY(oti.txt_to), to_comp);
 gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_to), 25);
 
-g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(origin_type_selected), &oti);
-g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(origin_type_selected), &oti);
-g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(origin_type_selected), &oti);
+g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(origin_type_selected_cb), &oti);
+g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(origin_type_selected_cb), &oti);
+g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(origin_type_selected_cb), &oti);
 
-#if WITH_HILDON && HILDON_AUTOCAP
+#if defined (WITH_HILDON) && defined (HILDON_AUTOCAP)
 g_object_set(G_OBJECT(oti.txt_from), HILDON_AUTOCAP, FALSE, NULL);
 g_object_set(G_OBJECT(oti.txt_to), HILDON_AUTOCAP, FALSE, NULL);
 #endif
@@ -405,7 +401,7 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
 
        from_escaped = gnome_vfs_escape_string(from);
        to_escaped = gnome_vfs_escape_string(to);
-       snprintf(buffer, sizeof(buffer), source_url, from_escaped, to_escaped);
+       g_snprintf(buffer, sizeof(buffer), source_url, from_escaped, to_escaped);
        g_free(from_escaped);
        g_free(to_escaped);
 
@@ -456,21 +452,18 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
                if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps))
                    && !g_slist_find_custom(_loc_list, from, (GCompareFunc) strcmp)) {
                        _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
-                       gtk_list_store_insert_with_values(_loc_model,
-                                                         &iter, INT_MAX, 0, from, -1);
+                       gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, from, -1);
                }
 
                /* Save Destination in Route Locations list. */
                if (!g_slist_find_custom(_loc_list, to, (GCompareFunc) strcmp)) {
                        _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
-                       gtk_list_store_insert_with_values(_loc_model,
-                                                         &iter,
-                                                         INT_MAX, 0,
-                                                         to, -1);
+                       gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, to, -1);
                }
 
                MACRO_BANNER_SHOW_INFO(_window, _("Route Downloaded"));
                g_free(rdl_data.bytes);
+               route_set_destination_from_last();
 
                /* Success! Get out of the while loop. */
                break;
@@ -489,37 +482,37 @@ return TRUE;
 WayPoint *
 find_nearest_waypoint(guint unitx, guint unity)
 {
-       WayPoint *wcurr;
-       WayPoint *wnear;
-       guint64 nearest_squared;
-       Point pos = { unitx, unity, 0, NAN };
-
-       wcurr = wnear = _route.whead;
-       if (wcurr && wcurr != _route.wtail) {
-               nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
-
-               while (wcurr++ != _route.wtail) {
-                       guint64 test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
-                       if (test_squared < nearest_squared) {
-                               wnear = wcurr;
-                               nearest_squared = test_squared;
-                       }
+WayPoint *wcurr;
+WayPoint *wnear;
+guint64 nearest_squared;
+Point pos = { unitx, unity, 0, NAN };
+
+wcurr = wnear = _route.whead;
+if (wcurr && wcurr != _route.wtail) {
+       nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+
+       while (wcurr++ != _route.wtail) {
+               guint64 test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+               if (test_squared < nearest_squared) {
+                       wnear = wcurr;
+                       nearest_squared = test_squared;
                }
        }
+}
 
-       if (wnear) {
-               /* Only use the waypoint if it is within a 6*_draw_width square drawn
-                * around the position. This is consistent with select_poi(). */
-               if (abs(unitx - wnear->point->unitx) <
-                   pixel2unit(3 * _draw_width)
-                   && abs(unity - wnear->point->unity) <
-                   pixel2unit(3 * _draw_width))
-                       return wnear;
-       }
+if (wnear) {
+       /* Only use the waypoint if it is within a 6*_draw_width square drawn
+        * around the position. This is consistent with select_poi(). */
+       if (abs(unitx - wnear->point->unitx) <
+           pixel2unit(3 * _draw_width)
+           && abs(unity - wnear->point->unity) <
+           pixel2unit(3 * _draw_width))
+               return wnear;
+}
 
-       MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
+MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
 
-       return NULL;
+return NULL;
 }
 
 /**
@@ -531,95 +524,90 @@ find_nearest_waypoint(guint unitx, guint unity)
 gboolean 
 route_update_nears(gboolean quick)
 {
-       gboolean ret = FALSE;
-       Point *curr, *near;
-       WayPoint *wcurr, *wnext;
-       guint64 near_dist_squared;
-
-       /* If we have waypoints (_next_way != NULL), then determine the "next
-        * waypoint", which is defined as the waypoint after the nearest point,
-        * UNLESS we've passed that waypoint, in which case the waypoint after
-        * that waypoint becomes the "next" waypoint. */
-       if (_next_way) {
-               /* First, set near_dist_squared with the new distance from
-                * _near_point. */
-               near = _near_point;
-               near_dist_squared = DISTANCE_SQUARED(_pos, *near);
-
-               /* Now, search _route for a closer point.  If quick is TRUE, then we'll
-                * only search forward, only as long as we keep finding closer points.
-                */
-               for (curr = _near_point; curr++ != _route.tail;) {
-                       if (curr->unity) {
-                               guint dist_squared =
-                                   DISTANCE_SQUARED(_pos, *curr);
-                               if (dist_squared <= near_dist_squared) {
-                                       near = curr;
-                                       near_dist_squared = dist_squared;
-                               } else if (quick)
-                                       break;
-                       }
-               }
-
-               /* Update _near_point. */
-               _near_point = near;
-               _near_point_dist_squared = near_dist_squared;
-
-               for (wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++) {
-                       if (wcurr->point < near
-                           /* Okay, this else if expression warrants explanation.  If the
-                            * nearest track point happens to be a waypoint, then we want to
-                            * check if we have "passed" that waypoint.  To check this, we
-                            * test the distance from _pos to the waypoint and from _pos to
-                            * _next_wpt, and if the former is increasing and the latter is
-                            * decreasing, then we have passed the waypoint, and thus we
-                            * should skip it.  Note that if there is no _next_wpt, then
-                            * there is no next waypoint, so we do not skip it in that case. */
-                           || (wcurr->point == near && quick
-                               && (_next_wpt && (DISTANCE_SQUARED(_pos, *near) > _next_way_dist_squared
-                                       && DISTANCE_SQUARED(_pos, *_next_wpt) < _next_wpt_dist_squared))))
-                               wnext = wcurr + 1;
-                       else
+gboolean ret = FALSE;
+Point *curr, *near;
+WayPoint *wcurr, *wnext;
+guint64 near_dist_squared;
+
+/* If we have waypoints (_next_way != NULL), then determine the "next
+ * waypoint", which is defined as the waypoint after the nearest point,
+ * UNLESS we've passed that waypoint, in which case the waypoint after
+ * that waypoint becomes the "next" waypoint. */
+if (_next_way) {
+       /* First, set near_dist_squared with the new distance from
+        * _near_point. */
+       near = _near_point;
+       near_dist_squared = DISTANCE_SQUARED(_gps->data, *near);
+
+       /* Now, search _route for a closer point.  If quick is TRUE, then we'll
+        * only search forward, only as long as we keep finding closer points.
+        */
+       for (curr = _near_point; curr++ != _route.tail;) {
+               if (curr->unity) {
+                       guint dist_squared = DISTANCE_SQUARED(_gps->data, *curr);
+                       if (dist_squared <= near_dist_squared) {
+                               near = curr;
+                               near_dist_squared = dist_squared;
+                       } else if (quick)
                                break;
                }
+       }
 
-               if (wnext == _route.wtail && (wnext->point < near
-                                             || (wnext->point == near && quick
-                                                 && (_next_wpt && (DISTANCE_SQUARED (_pos, *near) > _next_way_dist_squared
-                                                      && DISTANCE_SQUARED(_pos, *_next_wpt) < _next_wpt_dist_squared)))))
-               {
-                       _next_way = NULL;
-                       _next_wpt = NULL;
-                       _next_way_dist_squared = -1;
-                       _next_wpt_dist_squared = -1;
-                       ret = TRUE;
-               }
-               /* Only update _next_way (and consequently _next_wpt) if _next_way is
-                * different, and record that fact for return. */
-               else {
-                       if (!quick || _next_way != wnext) {
-                               _next_way = wnext;
-                               _next_wpt = wnext->point;
-                               if (_next_wpt == _route.tail)
-                                       _next_wpt = NULL;
-                               else {
-                                       while (!(++_next_wpt)->unity) {
-                                               if (_next_wpt == _route.tail) {
-                                                       _next_wpt = NULL;
-                                                       break;
-                                               }
+       /* Update _near_point. */
+       _near_point = near;
+       _near_point_dist_squared = near_dist_squared;
+
+       for (wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++) {
+               if (wcurr->point < near || (wcurr->point == near && quick 
+                               && (_next_wpt && (DISTANCE_SQUARED(_gps->data, *near) > _next_way_dist_squared
+                               && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared))))
+                   /* Okay, this else if expression warrants explanation.  If the
+                    * nearest track point happens to be a waypoint, then we want to
+                    * check if we have "passed" that waypoint.  To check this, we
+                    * test the distance from _gps to the waypoint and from _gps to
+                    * _next_wpt, and if the former is increasing and the latter is
+                    * decreasing, then we have passed the waypoint, and thus we
+                    * should skip it.  Note that if there is no _next_wpt, then
+                    * there is no next waypoint, so we do not skip it in that case. */
+                       wnext = wcurr + 1;
+               else
+                       break;
+       }
+
+       if (wnext == _route.wtail && (wnext->point < near || (wnext->point == near && quick
+                                         && (_next_wpt && (DISTANCE_SQUARED (_gps->data, *near) > _next_way_dist_squared
+                                              && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared)))))
+       {
+               _next_way = NULL;
+               _next_wpt = NULL;
+               _next_way_dist_squared = -1;
+               _next_wpt_dist_squared = -1;
+               ret = TRUE;
+       }
+       /* Only update _next_way (and consequently _next_wpt) if _next_way is
+        * different, and record that fact for return. */
+       else {
+               if (!quick || _next_way != wnext) {
+                       _next_way = wnext;
+                       _next_wpt = wnext->point;
+                       if (_next_wpt == _route.tail)
+                               _next_wpt = NULL;
+                       else {
+                               while (!(++_next_wpt)->unity) {
+                                       if (_next_wpt == _route.tail) {
+                                               _next_wpt = NULL;
+                                               break;
                                        }
                                }
-                               ret = TRUE;
                        }
-                       _next_way_dist_squared = DISTANCE_SQUARED(_pos, *wnext->point);
-                       if (_next_wpt)
-                               _next_wpt_dist_squared =
-                                   DISTANCE_SQUARED(_pos, *_next_wpt);
+                       ret = TRUE;
                }
+               _next_way_dist_squared = DISTANCE_SQUARED(_gps->data, *wnext->point);
+               if (_next_wpt)
+                       _next_wpt_dist_squared = DISTANCE_SQUARED(_gps->data, *_next_wpt);
        }
-
-       return ret;
+}
+return ret;
 }
 
 /**
@@ -629,28 +617,25 @@ route_update_nears(gboolean quick)
 void 
 route_find_nearest_point()
 {
+/* Initialize _near_point to first non-zero point. */
+_near_point = _route.head;
+while (!_near_point->unity && _near_point != _route.tail)
+       _near_point++;
 
-       /* Initialize _near_point to first non-zero point. */
-       _near_point = _route.head;
-       while (!_near_point->unity && _near_point != _route.tail)
-               _near_point++;
+/* Initialize _next_way. */
+if (_route.wtail == _route.whead - 1 || (_autoroute_data.enabled && _route.wtail == _route.whead))
+       _next_way = NULL;
+else
+       /* We have at least one waypoint. */
+       _next_way = (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
 
-       /* Initialize _next_way. */
-       if (_route.wtail == _route.whead - 1
-           || (_autoroute_data.enabled && _route.wtail == _route.whead))
-               _next_way = NULL;
-       else
-               /* We have at least one waypoint. */
-               _next_way =
-                   (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
-       _next_way_dist_squared = -1;
+_next_way_dist_squared = -1;
 
-       /* Initialize _next_wpt. */
-       _next_wpt = NULL;
-       _next_wpt_dist_squared = -1;
-
-       route_update_nears(FALSE);
+/* Initialize _next_wpt. */
+_next_wpt = NULL;
+_next_wpt_dist_squared = -1;
 
+route_update_nears(FALSE);
 }
 
 /**
@@ -659,81 +644,141 @@ route_find_nearest_point()
  * next waypoint.
  */
 gboolean 
-route_show_distance_to(Point * point)
+route_show_distance_to(Point *point)
 {
-       gchar buffer[80];
-       gfloat lat1, lon1, lat2, lon2;
-       gdouble sum = 0.0;
-
-       /* If point is NULL, use the next waypoint. */
-       if (point == NULL && _next_way)
-               point = _next_way->point;
-
-       /* If point is still NULL, return an error. */
-       if (point == NULL) {
-               return FALSE;
-       }
-
-       unit2latlon(_pos.unitx, _pos.unity, lat1, lon1);
-       if (point > _near_point) {
-               Point *curr;
-               /* Skip _near_point in case we have already passed it. */
-               for (curr = _near_point + 1; curr <= point; ++curr) {
-                       if (curr->unity) {
-                               unit2latlon(curr->unitx, curr->unity, lat2,
-                                           lon2);
-                               sum += calculate_distance(lat1, lon1, lat2, lon2);
-                               lat1 = lat2;
-                               lon1 = lon2;
-                       }
+gchar buffer[80];
+gdouble lat1, lon1, lat2, lon2;
+gdouble sum = 0.0;
+
+/* If point is NULL, use the next waypoint. */
+if (point == NULL && _next_way)
+       point = _next_way->point;
+
+/* If point is still NULL, return an error. */
+if (point == NULL)
+       return FALSE;
+
+unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1);
+if (point > _near_point) {
+       Point *curr;
+       /* Skip _near_point in case we have already passed it. */
+       for (curr = _near_point + 1; curr <= point; ++curr) {
+               if (curr->unity) {
+                       unit2latlon(curr->unitx, curr->unity, lat2, lon2);
+                       sum += calculate_distance(lat1, lon1, lat2, lon2);
+                       lat1 = lat2;
+                       lon1 = lon2;
                }
-       } else if (point < _near_point) {
-               Point *curr;
-               /* Skip _near_point in case we have already passed it. */
-               for (curr = _near_point - 1; curr >= point; --curr) {
-                       if (curr->unity) {
-                               unit2latlon(curr->unitx, curr->unity, lat2,
-                                           lon2);
-                               sum += calculate_distance(lat1, lon1, lat2, lon2);
-                               lat1 = lat2;
-                               lon1 = lon2;
-                       }
+       }
+} else if (point < _near_point) {
+       Point *curr;
+       /* Skip _near_point in case we have already passed it. */
+       for (curr = _near_point - 1; curr >= point; --curr) {
+               if (curr->unity) {
+                       unit2latlon(curr->unitx, curr->unity, lat2, lon2);
+                       sum += calculate_distance(lat1, lon1, lat2, lon2);
+                       lat1 = lat2;
+                       lon1 = lon2;
                }
-       } else {
-               /* Waypoint _is_ the nearest point. */
-               unit2latlon(_near_point->unitx, _near_point->unity, lat2, lon2);
-               sum += calculate_distance(lat1, lon1, lat2, lon2);
        }
+} else {
+       /* Waypoint _is_ the nearest point. */
+       unit2latlon(_near_point->unitx, _near_point->unity, lat2, lon2);
+       sum += calculate_distance(lat1, lon1, lat2, lon2);
+}
 
-       snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"),
-                sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
-       MACRO_BANNER_SHOW_INFO(_window, buffer);
+g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
+MACRO_BANNER_SHOW_INFO(_window, buffer);
 
-       return TRUE;
+return TRUE;
 }
 
 void 
 route_show_distance_to_next()
 {
+if (!route_show_distance_to(NULL)) {
+       MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint."));
+}
+}
 
-       if (!route_show_distance_to(NULL)) {
-               MACRO_BANNER_SHOW_INFO(_window,
-                                      _("There is no next waypoint."));
-       }
+void
+route_set_destination_from_last(void)
+{
+Point *p;
+gdouble lat,lon;
+if (_route.head == _route.tail)
+       return;
+
+/* Find last non-zero point. */
+for (p = _route.tail; !p->unity; p--) {
+}
+unit2latlon(p->unitx, p->unity, lat, lon);
+_dest.valid=TRUE;
+_dest.lat=lat;
+_dest.lon=lon;
 }
 
 void 
-route_show_distance_to_last()
+route_show_distance_to_last(void)
 {
+Point *p;
 
-       if (_route.head != _route.tail) {
-               /* Find last non-zero point. */
-               Point *p;
-               for (p = _route.tail; !p->unity; p--) {
-               }
-               route_show_distance_to(p);
-       } else {
-               MACRO_BANNER_SHOW_INFO(_window,
-                                      _("The current route is empty."));
+if (_route.head != _route.tail) {
+       /* Find last non-zero point. */
+       for (p = _route.tail; !p->unity; p--) {
+       }
+       route_show_distance_to(p);
+} else {
+       MACRO_BANNER_SHOW_INFO(_window, _("The current route is empty."));
        }
 }
+
+/***/
+
+GtkListStore *
+route_generate_store(Path *route)
+{
+WayPoint *wcurr;
+GtkTreeIter iter;
+GtkListStore *store;
+gchar buffer1[80];
+gchar buffer2[32];
+gdouble lat1, lon1, lat2, lon2;
+gdouble sum=0.0;
+
+if (route->whead==route->wtail)
+       return NULL;
+
+wcurr=route->whead;
+
+if (!wcurr->point)
+       return NULL;
+
+unit2latlon(wcurr->point->unitx, wcurr->point->unity, lat1, lon1);
+
+store = gtk_list_store_new(ROUTE_NUM_COLUMNS,G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+while (wcurr!=route->wtail) {
+       if (!wcurr)
+               break;
+
+       unit2latlon(wcurr->point->unitx, wcurr->point->unity, lat2, lon2);
+       g_snprintf(buffer1, sizeof(buffer1), "%.05f,%.05f", lat2, lon2);
+       sum += calculate_distance(lat1, lon1, lat2, lon2);
+       g_snprintf(buffer2, sizeof(buffer2), "%.02f %s", sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
+
+       lat1=lat2;
+       lon1=lon2;
+
+       gtk_list_store_append(store, &iter);
+       gtk_list_store_set(store, &iter,
+        ROUTE_LATLON, buffer1,
+               ROUTE_DISTANCE, buffer2,
+               ROUTE_WAYPOINT, wcurr->desc,
+               -1);
+
+       wcurr++;
+}
+
+return store;
+}