]> err.no Git - mapper/blobdiff - src/osm-db.c
Fixes to gstreamer element and caps handlings.
[mapper] / src / osm-db.c
index c7656eedec4348066a995e1a471f466af041e6aa..25f7d49c6ca853623e79389efda8ff908e01475b 100644 (file)
-#define _GNU_SOURCE
+/*
+ * This file is part of mapper
+ *
+ * Copyright (C) 2007 Kaj-Michael Lang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "config.h"
 
-#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <strings.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <math.h>
 #include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
 #include <sqlite3.h>
-#include <expat.h>
 
 #include "osm.h"
+#include "latlon.h"
+#include "osm-db.h"
+#include "settings.h"
+
+/* #define DEBUG_OSM */
+/* #define DEBUG_OSM_TIME */
+#define OSM_PLACE_CACHE_MAX_ITEMS (64)
+
+#define OSM_DB_PROGRESS_NUM (15000)
+
+/* Node search ranges */
+#define OSM_RANGE_START (16384)
+#define OSM_RANGE_STEP  (8192)
+#define OSM_RANGE_STOP  (65535)
+
+static sqlite3 *osmdb;
+static gboolean osm_db_ok;
 
 struct sql_select_stmt {
        sqlite3_stmt *select_way;
+       sqlite3_stmt *select_way2;
+       sqlite3_stmt *select_way_next_seg;
+       sqlite3_stmt *select_way_prev_seg;
+
        sqlite3_stmt *select_way_nodes;
        sqlite3_stmt *select_way_name;
+       sqlite3_stmt *select_way_name_nls;
+       sqlite3_stmt *select_way_name_search;
        sqlite3_stmt *select_way_ref;
        sqlite3_stmt *select_place;
-       sqlite3_stmt *select_near_place;
+       sqlite3_stmt *select_place_near;
+       sqlite3_stmt *select_place_search;
+
+       sqlite3_stmt *select_node_next;
+       sqlite3_stmt *select_node_prev;
 };
 static struct sql_select_stmt sql;
+static GTimer *dbt;
+static GtkProgressBar *dbpw=NULL;
+
+/* Cache hash tables */
+struct osm_place_cache {
+       GHashTable *cache;
+       guint hit;
+       guint miss;
+};
+static struct osm_place_cache pcache;
+
+static guint way_dist_range=OSM_RANGE_WAY;
+static gint sid=0;
 
-gboolean osm_way_get_nodes(osm_way *w);
+osm_way_node *osm_way_get_prev_node(osm_way *w);
+osm_way_node *osm_way_get_next_node(osm_way *w);
+
+/*****************************************************************************/
+
+void
+osm_set_way_range(guint sr)
+{
+way_dist_range=sr;
+}
+
+void
+osm_set_way_range_from_speed(gfloat speed)
+{
+if (speed>54.0)
+       way_dist_range=OSM_RANGE_WAY;
+else
+       way_dist_range=OSM_RANGE_WAY-lrint((speed/4)*1000);
+}
+
+/*****************************************************************************/
+
+static gboolean
+osm_progress_pulse(void)
+{
+if (!dbpw)
+       return FALSE;
+gtk_progress_bar_pulse(dbpw);
+return TRUE;
+}
+
+static int
+osm_progress(void *ud)
+{
+gtk_main_iteration_do(FALSE);
+return 0;
+}
+
+static void
+osm_progress_hide(sqlite3 *db)
+{
+if (!dbpw)
+       return;
+gtk_progress_bar_set_text(dbpw, "");
+gtk_progress_bar_set_fraction(dbpw, 0.0);
+sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
+}
+
+static void
+osm_progress_show(sqlite3 *db)
+{
+if (!dbpw)
+       return;
+gtk_progress_bar_set_text(dbpw, _("Searching..."));
+gtk_progress_bar_pulse(dbpw);
+gtk_main_iteration_do(FALSE);
+sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
+}
+
+void
+osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
+{
+if (dbpw!=NULL && w==NULL) {
+       osm_progress_hide(db);
+       if (sid!=0)
+               g_source_remove(sid);
+       sid=0;
+       dbpw=NULL;
+       return;
+}
+dbpw=w;
+if (w!=NULL) {
+       osm_progress_show(db);
+       sid=g_timeout_add(200, osm_progress_pulse, NULL);
+}
+}
+
+/*****************************************************************************/
 
 gboolean
 osm_db_prepare(sqlite3 *db)
 {
-/* Place */
 /* Select nearest place inside lat,lon+-range */
-if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
-                                       " lat,lon,places.nid,isin "
+if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
+                                       " ilat,ilon,places.nid,isin_p,isin_c "
                                        " from places,nodes where type=$TYPE "
                                        " and nodes.nid=places.nid "
-                                       " and lat between $LAT-$RANGE and $LAT+$RANGE"
-                                       " and lon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
-                   -1, &sql.select_near_place, NULL)!=SQLITE_OK)
+                                       " and ilat between $LAT-$RANGE and $LAT+$RANGE"
+                                       " and ilon between $LON-$RANGE and $LON+$RANGE order by d limit 1",
+                   -1, &sql.select_place_near, NULL)!=SQLITE_OK)
        return FALSE;
-/* Select place name, distance, location, parent-place and type with given ID */
 
-if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
-                                       " lat,lon,type,isin "
+/* Select place name, distance, location, parent-place and type with given ID */
+if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
+                                       " ilat,ilon,type,isin_p,isin_c "
                                        " from places,nodes where "
                                        " nodes.nid=places.nid "
-                                       " and places.nid=$NID order by dist limit 1",
+                                       " and places.nid=$NID order by d limit 1",
                    -1, &sql.select_place, NULL)!=SQLITE_OK)
        return FALSE;
 
+/* Search */
+if (sqlite3_prepare_v2(db, "select places.nid,name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
+                                       " rlat,rlon,type,isin_p,isin_c "
+                                       " from places,nodes where "
+                                       " nodes.nid=places.nid "
+                                       " and name like $NAME order by d limit 200",
+                   -1, &sql.select_place_search, NULL)!=SQLITE_OK)
+       return FALSE;
+
 /* Ways */
-/* Select neareset ways inside lat,lon+-range */
-if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
-                                       "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist, num"
-                                       " from way,way_seg,nodes"
-                                       " where wid=wsid and way_seg.node=nodes.nid "
-                                       " and lat between $LAT-$RANGE and $LAT+$RANGE "
-                                       " and lon between $LON-$RANGE and $LON+$RANGE "
-                                       " order by dist",
-                   -1, &sql.select_way, NULL)!=SQLITE_OK)
+/* Select nearest ways inside lat,lon+-range */
+if (sqlite3_prepare_v2(db, "select w.wid,type,nodes,flags,"
+                                       "(($LAT-n.ilat)*($LAT-n.ilat))+(($LON-n.ilon)*($LON-n.ilon)) as d,wn.f,wn.t,n.ilat,n.ilon "
+                                       " from way as w,way_n2n as wn,nodes as n "
+                                       " where w.wid=wn.wid and wn.f=n.nid "
+                                       " and n.ilat between $LAT-$RANGE and $LAT+$RANGE "
+                                       " and n.ilon between $LON-$RANGE and $LON+$RANGE "
+                                       " and w.type between $WTS and $WTY " 
+                                       " order by d",
+                   -1, &sql.select_way2, NULL)!=SQLITE_OK)
+       return FALSE;
+
+if (sqlite3_prepare_v2(db, "select w.wid,w.name as name,"
+                                       "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
+                                       " from way_names as w,way as ww where "
+                                       " ww.type between $WTS and $WTY and w.wid=ww.wid and w.name like $NAME "
+                                       " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
+                                       " and ww.lon between $LON-$RANGE and $LON+$RANGE "
+                                       " union "
+                                       " select w.wid,n.name as name,"
+                                       "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
+                                       " from way_names as w, way as ww,way_names_nls as n on w.wid=n.wid where "
+                                       " ww.type between $WTS and $WTY and w.wid=ww.wid and n.name like $NAME "
+                                       " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
+                                       " and ww.lon between $LON-$RANGE and $LON+$RANGE "
+                                       " order by name limit 200",
+                       -1, &sql.select_way_name_search, NULL)!=SQLITE_OK)
+       return FALSE;
+
+if (sqlite3_prepare_v2(db, "select wn.t,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=? and wn.t=nodes.nid limit 1",
+                   -1, &sql.select_way_next_seg, NULL)!=SQLITE_OK)
+       return FALSE;
+
+if (sqlite3_prepare_v2(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.t=? and wn.f=nodes.nid limit 1",
+                   -1, &sql.select_way_prev_seg, NULL)!=SQLITE_OK)
        return FALSE;
 
-/* Select way nodes */
-if (sqlite3_prepare_v2(db, "select num,lat,lon from way_seg,nodes where wsid=? and way_seg.node=nodes.nid order by num",
-                   -1, &sql.select_way_nodes, NULL)!=SQLITE_OK)
+/* Way name */
+if (sqlite3_prepare_v2(db, "select name from way_names where wid=?", -1, &sql.select_way_name, NULL)!=SQLITE_OK)
        return FALSE;
 
-/* Way name and ref */
-if (sqlite3_prepare_v2(db, "select name from way_names where wid=?",
-                   -1, &sql.select_way_name, NULL)!=SQLITE_OK)
+/* Way ref and int_ref */
+if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?", -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
        return FALSE;
 
-if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?",
-                   -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
+/* Get next, prev node + way information. For routing. */
+if (sqlite3_prepare_v2(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
+                       "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.f=?",
+                   -1, &sql.select_node_next, NULL)!=SQLITE_OK)
+       return FALSE;
+
+if (sqlite3_prepare_v2(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
+                       "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.t=?",
+                   -1, &sql.select_node_prev, NULL)!=SQLITE_OK)
        return FALSE;
 
 return TRUE;
 }
 
+void
+osm_deinit(void)
+{
+if (osmdb) {
+       if (sql.select_way_ref)
+               sqlite3_finalize(sql.select_way_ref);
+       if (sql.select_way_name)
+               sqlite3_finalize(sql.select_way_name);
+       if (sql.select_way_next_seg)
+               sqlite3_finalize(sql.select_way_next_seg);
+       if (sql.select_way_prev_seg)
+               sqlite3_finalize(sql.select_way_prev_seg);
+       if (sql.select_way_name_search)
+               sqlite3_finalize(sql.select_way_name_search);
+       if (sql.select_way2)
+               sqlite3_finalize(sql.select_way2);
+       if (sql.select_place)
+               sqlite3_finalize(sql.select_place);
+       if (sql.select_place_near)
+               sqlite3_finalize(sql.select_place_near);
+       if (sql.select_node_next)
+               sqlite3_finalize(sql.select_node_next);
+       if (sql.select_node_prev)
+               sqlite3_finalize(sql.select_node_prev);
+}
+osmdb=NULL;
+osm_db_ok=FALSE;
+memset(&sql, 0, sizeof(sql));
+g_hash_table_destroy(pcache.cache);
+pcache.hit=0;
+pcache.miss=0;
+g_timer_destroy(dbt);
+}
+
 gboolean
-osm_init()
+osm_init(sqlite3 **db)
+{
+osm_db_ok=FALSE;
+pcache.cache=g_hash_table_new(g_direct_hash, g_direct_equal);
+dbt=g_timer_new();
+
+if (!db || !*db) {
+       osmdb=NULL;
+       return FALSE;
+}
+
+osmdb=*db;
+memset(&sql, 0, sizeof(sql));
+if (osm_db_prepare(osmdb)==FALSE) {
+       g_printerr("Failed to prepare OSM SQL statements:");
+       g_printf("SQLITE: %s\n", sqlite3_errmsg(osmdb));
+       return FALSE;
+}
+osm_db_ok=TRUE;
+return TRUE;
+}
+
+/*****************************************************************************/
+
+osm_way_node *
+osm_way_node_new(guint id, gint lat, gint lon, gint flags)
+{
+osm_way_node *n=g_slice_new(osm_way_node);
+
+n->id=id;
+n->lat=lat;
+n->lon=lon;
+n->flags=flags;
+return n;
+}
+
+void
+osm_way_node_free(osm_way_node *n)
+{
+if (n)
+       g_slice_free(osm_way_node, n);
+}
+
+/**
+ * Free way nodes list 
+ */
+void
+osm_way_nodes_free(osm_way *w)
 {
+GList *iter;
+
+if (!w->nodes) 
+       return;
+
+for (iter=w->nodes; iter!=NULL; iter=iter->next)
+       g_slice_free(osm_way_node, (osm_way_node*)iter->data);
+
+g_list_free(w->nodes);
+}
+
+/**
+ * Free a osm_way structure
+ */
+void
+osm_way_free(osm_way *w)
+{
+if (!w)
+       return;
+osm_way_nodes_free(w);
+if (w->name)
+       g_free(w->name);
+if (w->ref)
+       g_free(w->ref);
+if (w->int_ref)
+       g_free(w->int_ref);
+g_slice_free(osm_way, w);
+}
+
+/*****************************************************************************/
+
+static void
+osm_place_free(osm_place *p)
+{
+if (p->name)
+       g_free(p->name);
+g_slice_free(osm_place, p);
+}
+
+static gboolean
+osm_place_remove(gpointer k, gpointer v, gpointer ud)
+{
+osm_place_free((osm_place *)v);
 return TRUE;
 }
 
+static osm_place *
+osm_place_new(void)
+{
+return g_slice_new0(osm_place);
+}
+
+static osm_place *
+osm_place_cache_lookup(guint32 id)
+{
+osm_place *r;
+r=g_hash_table_lookup(pcache.cache, GINT_TO_POINTER(id));
+if (r) 
+       pcache.hit++; 
+else 
+       pcache.miss++;
+
+g_debug("OSM: Cache %d/%d", pcache.hit, pcache.miss);
+return r;
+}
+
+static void
+osm_place_cache_add(osm_place *p)
+{
+if (osm_place_cache_lookup(p->id)==NULL)
+       g_hash_table_insert(pcache.cache, GINT_TO_POINTER(p->id), p);
+}
+
+static void
+osm_place_cache_gc(void)
+{
+guint r;
+
+r=g_hash_table_foreach_remove(pcache.cache, osm_place_remove, NULL);
+g_debug("OSM: Cache cleared (%d)", r);
+pcache.hit=0;
+pcache.miss=0;
+}
+
+static void
+osm_place_update_distance(osm_place *p, gint lat, gint lon)
+{
+gdouble lam, lom;
+
+lam=(gdouble)((lat-p->lat)*(lat-p->lat));
+lom=(gdouble)((lon-p->lon)*(lon-p->lon));
+
+p->dist=sqrt(lam+lom);
+}
+
 /**
  * Get place with given id and distance to current location
  */
 gboolean
-osm_place_get(guint32 id, gint lat, gint lon, osm_place *n)
+osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr)
 {
+osm_place *n;
+
+n=*nr;
+n=osm_place_cache_lookup(id);
+if (n) {
+       osm_place_update_distance(n, lat, lon);
+       return TRUE;
+}
+n=NULL;
+
+/* XXX: better place for this */
+if (g_hash_table_size(pcache.cache)>OSM_PLACE_CACHE_MAX_ITEMS)
+       osm_place_cache_gc();
+
 sqlite3_clear_bindings(sql.select_place);
 sqlite3_reset(sql.select_place);
 
@@ -104,6 +465,7 @@ if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
        const gchar *place;
        guint32 dist;
 
+       n=osm_place_new();
        place=sqlite3_column_text(sql.select_place, 0);
        n->name=g_strdup(place);
        dist=sqlite3_column_int(sql.select_place, 1);
@@ -111,19 +473,21 @@ if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
        n->lat=sqlite3_column_int(sql.select_place, 2);
        n->lon=sqlite3_column_int(sql.select_place, 3);
        n->type=sqlite3_column_int(sql.select_place, 4);
-       n->isin=sqlite3_column_int(sql.select_place, 5);
+       n->isin_p=sqlite3_column_int(sql.select_place, 5);
+/*     n->isin_c=sqlite3_column_int(sql.select_place, 6); */
        return TRUE;
 }
 return FALSE;
 }
 
 /**
- * Search for the nearest place, type
+ * Search for the nearest place with given type
  */
 gboolean
-osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place *n)
+osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
 {
 gint range;
+osm_place *n=NULL;
 
 switch (type) {
        case NODE_PLACE_SUBURB:
@@ -142,123 +506,173 @@ switch (type) {
        break;
 }
 
-sqlite3_clear_bindings(sql.select_near_place);
-sqlite3_reset(sql.select_near_place);
+sqlite3_clear_bindings(sql.select_place_near);
+sqlite3_reset(sql.select_place_near);
 
-if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) ||
-    SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) ||
-    SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) ||
-    SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) {
+if (SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 1, lat) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 2, lon) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 3, type) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 4, range)) {
        g_printerr("Failed to bind values for near place\n");
        return FALSE;
 }
 
-if (n->name) {
-       g_free(n->name);
-       n->name=NULL;
-}
-n->isin=n->lat=n->lon=n->dist=0;
-if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
+n=osm_place_new();
+n->isin_p=n->lat=n->lon=n->dist=0;
+if (SQLITE_ROW == sqlite3_step(sql.select_place_near)) {
        const gchar *place;
        guint32 dist;
 
-       place=sqlite3_column_text(sql.select_near_place, 0);
+       place=sqlite3_column_text(sql.select_place_near, 0);
        n->name=g_strdup(place);
-       dist=sqlite3_column_int(sql.select_near_place, 1);
+       dist=sqlite3_column_int(sql.select_place_near, 1);
        n->dist=sqrt((double)dist);
-       n->lat=sqlite3_column_int(sql.select_near_place, 2);
-       n->lon=sqlite3_column_int(sql.select_near_place, 3);
-       n->id=sqlite3_column_int(sql.select_near_place, 4);
-       n->isin=sqlite3_column_int(sql.select_near_place, 5);
+       n->lat=sqlite3_column_int(sql.select_place_near, 2);
+       n->lon=sqlite3_column_int(sql.select_place_near, 3);
+       n->id=sqlite3_column_int(sql.select_place_near, 4);
+       n->isin_p=sqlite3_column_int(sql.select_place_near, 5);
+/*     n->isin_c=sqlite3_column_int(sql.select_place_near, 6); */
        n->type=type;
 
-       g_printf("Place(%d): %s distance: %f\n", type, place, n->dist);
+       osm_place_cache_add(n);
+
+       *nr=n;
        return TRUE;
 }
+*nr=n;
 return FALSE;
 }
 
-/* Way helper */
+/*
+ * Way helper 
+ *
+ */
 static GList *
 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
 {
 GList *ways=NULL;
 osm_way *w;
+gulong tms;
+guint wc=0;
 
-sqlite3_reset(sql.select_way);
-sqlite3_clear_bindings(sql.select_way);
+sqlite3_reset(sql.select_way2);
+sqlite3_clear_bindings(sql.select_way2);
 
-if (SQLITE_OK != sqlite3_bind_int(sql.select_way, 1, lat) ||
-    SQLITE_OK != sqlite3_bind_int(sql.select_way, 2, lon) ||
-    SQLITE_OK != sqlite3_bind_int(sql.select_way, 3, range)) {
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way2, 1, lat) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way2, 2, lon) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way2, 3, range) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way2, 4, WAY_ROAD_START) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way2, 5, WAY_ROAD_END)) {
        g_printerr("Failed to bind values for way\n");
        return NULL;
 }
 
-while (SQLITE_ROW == sqlite3_step(sql.select_way)) {
+#ifdef DEBUG_OSM_TIME
+g_timer_start(dbt);
+#endif
+
+while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
        guint32 dist;
+       gint lat, lon;
 
+       wc++;
        w=g_slice_new0(osm_way);
-       w->id=sqlite3_column_int(sql.select_way, 0);
-       w->type=sqlite3_column_int(sql.select_way, 1);
-       w->nodecnt=sqlite3_column_int(sql.select_way, 2);
-       w->flags=sqlite3_column_int(sql.select_way, 3);
-       dist=sqlite3_column_int(sql.select_way, 4);
+       w->id=sqlite3_column_int(sql.select_way2, 0);
+       w->type=sqlite3_column_int(sql.select_way2, 1);
+       w->nodecnt=sqlite3_column_int(sql.select_way2, 2);
+       w->flags=sqlite3_column_int(sql.select_way2, 3);
+       dist=sqlite3_column_int(sql.select_way2, 4);
        w->dist=sqrt((gdouble)dist);
-       w->node_num=sqlite3_column_int(sql.select_way, 5);
+       w->f=sqlite3_column_int(sql.select_way2, 5);
+       w->t=sqlite3_column_int(sql.select_way2, 6);
+
+       lat=sqlite3_column_int(sql.select_way2, 7);
+       lon=sqlite3_column_int(sql.select_way2, 8);
+
+       w->node_f=osm_way_node_new(w->f, lat, lon, 0);
+
        ways=g_list_prepend(ways, w);
 }
 
+#ifdef DEBUG_OSM_TIME
+g_timer_stop(dbt);
+g_printf("Query took: %f sec, found: %d ways\n", g_timer_elapsed(dbt, &tms), wc);
+#endif
+
 return ways;
 }
 
-static gdouble magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+/*****************************************************************************/
+
+GSList *
+osm_get_route_node(guint nid, osm_node_direction d)
 {
-gdouble x,y;
-x=x2-x1;
-y=y2-y1;
+GSList *r=NULL;
+osm_way *w;
+guint wc=0;
+sqlite3_stmt *psql=NULL;
 
-return sqrt((x*x)+(y*y));
+switch (d) {
+       case OSM_NODE_NEXT:
+               psql=sql.select_node_next;
+       break;
+       case OSM_NODE_PREV:
+               psql=sql.select_node_prev;
+       break;
+       default:
+               g_assert_not_reached();
+       break;
 }
 
-gboolean distance_point_to_line(gint x, gint y, gint x1, gint y1, gint x2, gint y2, gdouble *d)
-{
-gdouble lm,u;
-gdouble ix,iy;
-gdouble tmp,tx1,tx2,ty1,ty2;
+sqlite3_reset(psql);
+sqlite3_clear_bindings(psql);
 
-#if 0
-if (x1>x2) {
-       tx1=x2;
-       ty1=y2;
-       x2=x1;
-       y2=y1;
-       x1=tx1;
-       y1=ty1;
+if (SQLITE_OK != sqlite3_bind_int(psql, 1, nid)) {
+       g_printerr("Failed to bind values for route node\n");
+       return NULL;
 }
+
+while (SQLITE_ROW == sqlite3_step(psql)) {
+       gdouble lat, lon;
+
+       wc++;
+       w=g_slice_new0(osm_way);
+       w->id=sqlite3_column_int(psql, 0);
+       w->type=sqlite3_column_int(psql, 1);
+       w->flags=sqlite3_column_int(psql, 2);
+       w->speed=sqlite3_column_int(psql, 3);
+
+       lat=sqlite3_column_double(psql, 5);
+       lon=sqlite3_column_double(psql, 6);
+
+       w->f=sqlite3_column_int(psql, 7);
+       w->t=sqlite3_column_int(psql, 8);
+#if 0
+       w->node=
+       w->node->flags=sqlite3_column_int(psql, 9);
+       w->node->links=sqlite3_column_int(psql, 10);
 #endif
 
-lm=magnitude((gdouble)x1,(gdouble)y1,(gdouble)x2,(gdouble)y2);
-tmp=(gdouble)((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
-u=tmp/(lm*lm);
+       r=g_slist_prepend(r, w);
+}
 
-g_printf("DPL: tmp %f u %f lm %f\n", tmp, u, lm);
+return r;
+}
 
-g_printf("DPLX: (%d/%d) (%d %d)-(%d %d)\n",
-       x,y,
-       x1,y1,
-       x2,y2);
 
-if (u<0.0f || u>1.0f)
+/*****************************************************************************/
+gboolean 
+osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
+{
+if (!f) {
+       return FALSE;
+}
+
+if (!t) {
        return FALSE;
-ix=(gdouble)x1+u*(gdouble)(x2-x1);
-iy=(gdouble)y1+u*(gdouble)(y2-y1);
-*d=magnitude((gdouble)x,(gdouble)y, ix, iy);
-return TRUE;
+}
+
+return distance_point_to_line((gdouble)lon, (gdouble)lat, (gdouble)f->lon, (gdouble)f->lat, (gdouble)t->lon, (gdouble)t->lat, d);
 }
 
 /**
@@ -270,92 +684,72 @@ return TRUE;
  *   - Store result if closer than before
  * - Return closest way
  */
+
+#define START_DIST (900000.0)
+
 osm_way *
 osm_find_nearest_way(gint lat, gint lon)
 {
 GList *iter;
 GList *w=NULL;
-guint range=8192;
+guint range=OSM_RANGE_START;
 osm_way *cw=NULL;
+gdouble pdist=START_DIST, dist_n, dist_p;
 
-while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=65536) {
-       range=range<<1;
+while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=OSM_RANGE_STOP) {
+       range+=OSM_RANGE_STEP;
        g_printf("Trying with range: %d\n", range);
 }
+#ifdef DEBUG_OSM
+g_printf("Found %d ways withing range %d\n", g_list_length(w), range);
+#endif
 
-g_printf("Found ways: %d\n", g_list_length(w));
+if (g_list_length(w)==0)
+       return NULL;
 
-switch (g_list_length(w)) {
-       case 0:
-               return NULL;
-       break;
-       case 1:
-               cw=w->data;
-       break;
-       default:
-       {
-               gint dist=900000, ndist;
-               gdouble pdist=900000.0, pndist=9000000.0;
-
-               for (iter=w; iter!=NULL; iter=iter->next) {
-                       osm_way_node *wnf;
-                       osm_way_node *wnt;
-
-                       osm_way *way=(osm_way*)iter->data;
-
-                       g_printf("C*** WAY %d (%d) HAS %d NODES, nearest is %d\n", 
-                               way->id, way->type, way->nodecnt, way->node_num);
-
-                       if (osm_way_get_nodes(way)==FALSE)
-                               continue;
-
-                       if (way->nodes==0) {
-                               g_printerr("Way with 0 nodes ? Skipping\n");
-                               continue;
-                       }
-
-                       wnf=g_list_nth_data(way->nodes, way->node_num);
-                       if (!wnf)
-                               continue;
-
-                       g_printf("----EVAL-START:\n");
-                       if (way->node_num==way->nodecnt) {
-                               g_print("  <- Last\n");
-                               wnt=g_list_nth_data(way->nodes, way->nodecnt-1);
-                               if (!wnt)
-                                       continue;
-                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
-                                       continue;
-                       } else if (way->node_num==0) {
-                               g_print("  First %d ->\n", wnf->num);
-                               wnt=g_list_nth_data(way->nodes, 1);
-                               if (!wnt)
-                                       continue;
-                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
-                                       continue;
-                       } else {
-                               g_print("  <->\n");
-                               wnt=g_list_nth_data(way->nodes, way->node_num-1);
-                               if (!wnt)
-                                       continue;
-                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE) {
-                                       wnt=g_list_nth_data(way->nodes, way->node_num+1);
-                                       if (!wnt)
-                                               continue;
-                                       if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
-                                               continue;
-                               }
-                       }
-                       g_printf("----EVAL-DONE: %d <-> %d\n", wnf->num, wnt->num);
-
-                       g_printf("WD: New: %f Prev:%f\n", pndist, pdist);
-                       if (pndist<pdist) {
-                               pdist=pndist;
-                               cw=way;
-                       }
+for (iter=w; iter!=NULL; iter=iter->next) {
+       osm_way_node *wnn;
+       osm_way_node *wnp;
+       osm_way *way=(osm_way*)iter->data;
+
+       g_debug("Way: %d (%d) has %d nodes, nearest is %d,%d",
+               way->id, way->type, way->nodecnt, way->f, way->t);
+
+       way->node_t=NULL;
+
+       wnn=osm_way_get_next_node(way);
+       if (osm_way_distance(lat, lon, way->node_f, wnn, &dist_n)==FALSE) {
+               osm_way_node_free(wnn);
+               dist_n=START_DIST;
+       } else if (dist_n<pdist) {
+               pdist=dist_n;
+               cw=way;
+               way->distance=dist_n;
+               way->node_t=wnn;
+               g_debug("#1 distance: %f (%f)", dist_n, pdist);
+       }
+
+       wnp=osm_way_get_prev_node(way);
+       if (osm_way_distance(lat, lon, way->node_f, wnp, &dist_p)==FALSE) {
+               osm_way_node_free(wnp);
+               dist_p=START_DIST;
+       } else if (dist_p<pdist) {
+               pdist=dist_p;
+               cw=way;
+               way->distance=dist_n;
+               if (way->node_t) {
+                       osm_way_node_free(wnn);
                }
+               way->node_t=wnp;
+               g_debug("#2 distance: %f (%f)", dist_p, pdist);
+       }
+
+       g_debug("Found close way, distance: %f %f (%f)", dist_n, dist_p, pdist);
+
+       if (!cw) {
+               osm_way_free(way);
+               way=NULL;
        }
-       break;
 }
 
 g_list_free(w);
@@ -369,16 +763,71 @@ if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK ||
                osm_way_get_ref(cw);
 }
 
-g_printf("Way: %d %d %d %d: %s %s %s\n", 
-       cw->id, cw->type, cw->flags,
-       cw->nodes, cw->dist, cw->name, 
-       cw->ref, cw->int_ref);
+g_debug("Found way: (ID: %d): [%s]:[%s][%s]", cw->id, cw->name, cw->ref, cw->int_ref);
+g_debug("T: %d F: %d N#: %d D: %f", cw->type, cw->flags, cw->nodecnt, cw->dist);
+g_debug("\tNF#: %d NT#: %d (D: %f)", cw->f, cw->t, cw->distance);
 
 return cw;
 }
 
+/* XXX: These two should be combined to save memory */
+/**
+ * Get previous node/segment of given way node
+ *
+ */
+osm_way_node *
+osm_way_get_prev_node(osm_way *w)
+{
+sqlite3_reset(sql.select_way_prev_seg);
+sqlite3_clear_bindings(sql.select_way_prev_seg);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 1, w->id) ||
+       SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 2, w->f)  ) {
+       g_printerr("Failed to bind values for prev seg\n");
+       return NULL;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_prev_seg)) {
+       return osm_way_node_new(
+               sqlite3_column_int(sql.select_way_prev_seg, 0),
+               sqlite3_column_int(sql.select_way_prev_seg, 1),
+               sqlite3_column_int(sql.select_way_prev_seg, 2),
+               0);
+}
+
+return NULL;
+}
+
+/**
+ * Get next node/segment of given way node
+ *
+ */
+osm_way_node *
+osm_way_get_next_node(osm_way *w)
+{
+sqlite3_reset(sql.select_way_next_seg);
+sqlite3_clear_bindings(sql.select_way_next_seg);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 1, w->id) ||
+       SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 2, w->f)  ) {
+       g_printerr("Failed to bind values for next seg\n");
+       return NULL;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_next_seg)) {
+       return osm_way_node_new(
+               sqlite3_column_int(sql.select_way_next_seg, 0),
+               sqlite3_column_int(sql.select_way_next_seg, 1),
+               sqlite3_column_int(sql.select_way_next_seg, 2),
+               0);
+}
+
+return NULL;
+}
+
 /**
  * Get list of nodes for given way
+ *
  */
 gboolean
 osm_way_get_nodes(osm_way *w)
@@ -398,7 +847,7 @@ while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
        osm_way_node *n;
 
        n=g_slice_new(osm_way_node);
-       n->num=sqlite3_column_int(sql.select_way_nodes, 0);
+       n->id=sqlite3_column_int(sql.select_way_nodes, 0);
        n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
        n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
        w->nodes=g_list_append(w->nodes, n);
@@ -407,6 +856,10 @@ while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
 return (w->nodes==NULL) ? FALSE : TRUE;
 }
 
+/**
+ * Get way name
+ *
+ */
 gboolean
 osm_way_get_name(osm_way *w)
 {
@@ -426,6 +879,33 @@ if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
 return FALSE;
 }
 
+#if 0
+gboolean
+osm_way_get_name_nls(osm_way *w)
+{
+sqlite3_reset(sql.select_way_name_nls);
+sqlite3_clear_bindings(sql.select_way_name_nls);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
+       SQLITE_OK != sqlite3_bind_) {
+       g_printerr("Failed to bind values for way name nls\n");
+       return FALSE;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
+       const gchar *place;
+       place=sqlite3_column_text(sql.select_way_name_nls, 0);
+       w->name=g_strdup(place);
+}
+return FALSE;
+}
+#endif
+
+
+/**
+ * Get Way ref and int_ref
+ *
+ */
 gboolean
 osm_way_get_ref(osm_way *w)
 {
@@ -447,16 +927,261 @@ if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
 return FALSE;
 }
 
-void
-osm_way_free(osm_way *w)
+/******************************************************************************/
+
+/**
+ * Try to figure out where the given lat,lon is. Fills in the given struct,
+ * with street, secondary (suburb) and primary (city,town,village) location.
+ * Will try to minimize the amount of database access by skipping queries
+ * if we haven't moved or if we don't know where we are.
+ *
+ */
+gboolean 
+osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc)
 {
-if (w->nodes)
-       g_list_free(w->nodes);
-if (w->name)
-       g_free(w->name);
-if (w->ref)
-       g_free(w->ref);
-if (w->int_ref)
-       g_free(w->int_ref);
-g_slice_free(osm_way, w);
+gdouble dist;
+gboolean check_place=FALSE;
+gulong d;
+
+if (map_loc->valid==FALSE) {
+       map_loc->lat=lat;
+       map_loc->lon=lon;
+       map_loc->valid=TRUE;
+       d=way_dist_range*5;
+} else {
+       d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
+}
+
+/* Check if we are still near the same way as last time */
+if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
+       /* We are probably on the same way as last time */
+       if ( (dist>(gdouble)way_dist_range) || (fabs(heading-map_loc->heading)>10.0)) {
+               /* We have moved a large amount, check way again */
+               g_debug("Distance %f > %f range or angle %f > 10.0, checking location", 
+                       dist, way_dist_range, fabs(heading-map_loc->heading));
+               osm_way_free(map_loc->street);
+               map_loc->street=osm_find_nearest_way(lat, lon);
+               check_place=TRUE;
+               map_loc->changed=TRUE;
+       } else {
+#if 0
+               g_printf("*** No change in location: %f %d\n", dist, way_dist_range);
+#endif
+               /* We are still on the same way as last time */
+               check_place=FALSE;
+               map_loc->changed=FALSE;
+       }
+       map_loc->lat=lat;
+       map_loc->lon=lon;
+} else {
+       /* We didn't know our location, so check it, but only if we have moved */
+       if (d>way_dist_range) {
+               g_print("*** Must check location\n");
+               check_place=TRUE;
+               osm_way_free(map_loc->street);
+               map_loc->street=osm_find_nearest_way(lat, lon);
+#if 0
+               map_loc->lat=lat;
+               map_loc->lon=lon;
+#endif
+       } 
+
+       if (!map_loc->street) {
+               g_print("*** Street not known\n");
+               map_loc->nfcnt++;
+               map_loc->changed=TRUE;
+       } else {
+               g_print("*** Street known\n");
+               map_loc->nfcnt=0;
+               map_loc->changed=TRUE;
+               check_place=TRUE;
+       }
+}
+
+if (map_loc->changed==TRUE) {
+       map_loc->heading=heading;
+}
+
+#if 0
+g_printf("NFC: %d\n", map_loc->nfcnt);
+g_printf("D: %ld %ld\n", d,(gulong)way_dist_range);
+#endif
+
+if (check_place==TRUE && d>way_dist_range*4) {
+       gboolean fs;
+
+       fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
+       if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin_p!=0) {
+               if (osm_place_get(map_loc->secondary->isin_p, lat, lon, &(map_loc->primary))==FALSE) {
+                       if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
+                               g_printf("Near city: %s\n", map_loc->primary->name);
+                       else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
+                               g_printf("Near town: %s\n", map_loc->primary->name);
+                       else
+                               g_printf("Unknown\n");
+               } else {
+                       g_printf("In: %s\n", map_loc->primary ? map_loc->primary->name : "?");
+               }
+       } else if (map_loc->street && map_loc->street->isin_p!=0) {
+               if (osm_place_get(map_loc->street->isin_p, lat, lon, &map_loc->primary)==FALSE) {
+                       g_printf("Street location not know.\n");
+               } else {
+                       g_printf("Street is in: %s\n", map_loc->primary ? map_loc->primary->name : "?");
+               }
+       } else {
+               if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
+                       g_printf("Near city: %s\n", map_loc->primary->name);
+               else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
+                       g_printf("Near town: %s\n", map_loc->primary->name);
+               else
+                       g_printf("Unknown\n");
+
+       }
+}
+
+return map_loc->street ? TRUE : FALSE;
+}
+
+/**
+ * osm_place_search
+ */
+gboolean
+osm_place_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
+{
+GtkTreeIter iter;
+gchar *ltext=NULL;
+guint rows=0;
+gchar tmp1[16], tmp2[16];
+gdouble range=6;
+
+ltext=g_strdup_printf("%s%%", text);
+
+if (SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 1, lat) ||
+    SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 2, lon) ||
+       SQLITE_OK != sqlite3_bind_text(sql.select_place_search,   3, ltext, -1, SQLITE_TRANSIENT)) {
+               g_printerr("Failed to bind values for sql.select_place_search\n");
+               sqlite3_clear_bindings(sql.select_place_search);
+               g_free(ltext);
+               return FALSE;
+}
+
+if (ltext)
+       g_free(ltext);
+
+*store = gtk_list_store_new(ITEM_NUM_COLUMNS, 
+                               G_TYPE_INT,             /* ID */
+                               G_TYPE_INT,             /*  */
+                               G_TYPE_DOUBLE,  /* Latitude */
+                               G_TYPE_DOUBLE,  /* Longitude */
+                               G_TYPE_DOUBLE,  /* Distance */
+                               G_TYPE_STRING,  /* Lat/Lon */
+                               G_TYPE_STRING,  /* Label */
+                               G_TYPE_STRING,  /* Desc. */
+                               G_TYPE_STRING,  /* Category */
+                               G_TYPE_STRING,  /* Dummy */
+                               G_TYPE_STRING); /* Dummy */
+
+while (SQLITE_ROW == sqlite3_step(sql.select_place_search)) {
+       gdouble rlat, rlon, dist;
+
+       rlat=sqlite3_column_double(sql.select_place_search, 3);
+       rlon=sqlite3_column_double(sql.select_place_search, 4);
+       lat_format(_degformat, rlat, tmp1);
+       lon_format(_degformat, rlon, tmp2);
+       dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
+
+       gtk_list_store_append(*store, &iter);
+       gtk_list_store_set(*store, &iter,
+               ITEM_ID, sqlite3_column_int(sql.select_place_search, 0),
+               ITEM_LAT, rlat,
+               ITEM_LON, rlon,
+               ITEM_DIST, dist,
+               ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
+               ITEM_LABEL, sqlite3_column_text(sql.select_place_search, 1),
+               -1);
+       rows++;
+}
+
+g_printf("Found: %d places\n", rows);
+
+sqlite3_reset(sql.select_place_search);
+sqlite3_clear_bindings(sql.select_place_search);
+
+return TRUE;
+}
+
+/**
+ * osm_way_search
+ *
+ * Search for a street(way) starting with given 'text', next given lat/lon
+ *
+ */
+gboolean
+osm_way_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
+{
+GtkTreeIter iter;
+gchar *ltext=NULL;
+guint rows=0;
+gchar tmp1[16], tmp2[16];
+gdouble range=6;
+
+g_printf("Way Search: [%s] around %.6f %.6f\n", text, lat, lon);
+
+ltext=g_strdup_printf("%s%%", text);
+
+if (SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 1, lat) ||
+    SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 2, lon) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,   3, WAY_ROAD_START) ||
+    SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,    4, WAY_ROAD_END) ||
+    SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 6, range) ||
+       SQLITE_OK != sqlite3_bind_text(sql.select_way_name_search,   5, ltext, -1, SQLITE_TRANSIENT)) {
+               g_printerr("Failed to bind values for sql.select_way_name_search\n");
+               sqlite3_clear_bindings(sql.select_way_name_search);
+               g_free(ltext);
+               return FALSE;
+}
+
+if (ltext)
+       g_free(ltext);
+
+*store = gtk_list_store_new(ITEM_NUM_COLUMNS, 
+                               G_TYPE_INT,             /* ID */
+                               G_TYPE_INT,             /*  */
+                               G_TYPE_DOUBLE,  /* Latitude */
+                               G_TYPE_DOUBLE,  /* Longitude */
+                               G_TYPE_DOUBLE,  /* Distance */
+                               G_TYPE_STRING,  /* Lat/Lon */
+                               G_TYPE_STRING,  /* Label */
+                               G_TYPE_STRING,  /* Desc. */
+                               G_TYPE_STRING,  /* Category */
+                               G_TYPE_STRING,  /* Dummy */
+                               G_TYPE_STRING); /* Dummy */
+
+while (SQLITE_ROW == sqlite3_step(sql.select_way_name_search)) {
+       gdouble rlat, rlon, dist;
+
+       rlat=sqlite3_column_double(sql.select_way_name_search, 3);
+       rlon=sqlite3_column_double(sql.select_way_name_search, 4);
+       lat_format(_degformat, rlat, tmp1);
+       lon_format(_degformat, rlon, tmp2);
+       dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
+
+       gtk_list_store_append(*store, &iter);
+       gtk_list_store_set(*store, &iter,
+               ITEM_ID, sqlite3_column_int(sql.select_way_name_search, 0),
+               ITEM_LAT, rlat,
+               ITEM_LON, rlon,
+               ITEM_DIST, dist,
+               ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
+               ITEM_LABEL, sqlite3_column_text(sql.select_way_name_search, 1),
+               -1);
+       rows++;
+}
+
+g_printf("Found: %d items\n", rows);
+
+sqlite3_reset(sql.select_way_name_search);
+sqlite3_clear_bindings(sql.select_way_name_search);
+
+return TRUE;
 }