]> err.no Git - mapper/blob - src/osm-db.c
More map widget integration changes
[mapper] / src / osm-db.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 #include "config.h"
21
22 #include <unistd.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <sys/types.h>
26 #include <math.h>
27 #include <glib.h>
28 #include <glib/gstdio.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31 #include <sqlite3.h>
32
33 #include "osm.h"
34 #include "latlon.h"
35 #include "db.h"
36 #include "osm-db.h"
37 #include "settings.h"
38 #include "osm-sql-tables.h"
39
40 /* #define DEBUG_OSM */
41 #define DEBUG_OSM_TIME
42 #define OSM_PLACE_CACHE_MAX_ITEMS (64)
43
44 #define OSM_DB_PROGRESS_NUM (30000)
45
46 /* Node search ranges */
47 #define OSM_RANGE_START (16384*2)
48 #define OSM_RANGE_STEP  (8192)
49 #define OSM_RANGE_STOP  (65535)
50
51 /* Way range for searching again */
52 #define OSM_RANGE_WAY (12000)
53
54 #ifdef DEBUG_OSM_TIME
55 #define QT_START { g_timer_start(dbt); }
56 #define QT_END { g_timer_stop(dbt); g_debug("Query took: %f sec", g_timer_elapsed(dbt, &tms)); }
57 #else
58 #define QT_START 
59 #define QT_END
60 #endif
61
62 static sqlite3 *osmdb;
63 static gboolean osm_db_ok;
64
65 struct sql_select_stmt {
66         sqlite3_stmt *select_way;
67         sqlite3_stmt *select_way2;
68         sqlite3_stmt *select_way_next_seg;
69         sqlite3_stmt *select_way_prev_seg;
70
71         sqlite3_stmt *select_way_nodes;
72         sqlite3_stmt *select_way_name;
73         sqlite3_stmt *select_way_name_nls;
74         sqlite3_stmt *select_way_name_search;
75         sqlite3_stmt *select_way_ref;
76         sqlite3_stmt *select_place;
77         sqlite3_stmt *select_place_near;
78         sqlite3_stmt *select_place_search;
79
80         sqlite3_stmt *select_node_next;
81         sqlite3_stmt *select_node_prev;
82 };
83 static struct sql_select_stmt sql;
84 static GTimer *dbt;
85 static gulong tms;
86 static GtkProgressBar *dbpw=NULL;
87
88 static const gchar *osm_tables[]={
89         OSM_TABLE_NODES,
90         OSM_TABLE_NODE_TAGS,
91         OSM_TABLE_WAY,
92         OSM_TABLE_WAY_TAGS,
93         OSM_TABLE_WAY_UPDATES,
94         OSM_TABLE_WAY_N2N,
95         OSM_TABLE_WAY_NAMES,
96         OSM_TABLE_WAY_PC,
97         OSM_TABLE_WAY_NAMES_NLS,
98         OSM_TABLE_WAY_REF,
99         OSM_TABLE_PLACES,
100         OSM_TABLE_POI,
101         OSM_TABLE_POI_CATEGORY, 
102         NULL};
103
104 static const gchar *osm_indexes[]={
105         OSM_INDEX_1,
106         OSM_INDEX_2,
107         OSM_INDEX_3,
108         OSM_INDEX_4,
109         OSM_INDEX_5,
110         OSM_INDEX_6,
111         OSM_INDEX_7,
112         OSM_INDEX_8,
113         OSM_INDEX_9,
114         OSM_INDEX_10,
115         OSM_INDEX_11,
116         OSM_INDEX_12,
117         OSM_INDEX_13,
118         OSM_INDEX_14,
119         OSM_INDEX_15,
120         OSM_INDEX_16,
121         OSM_INDEX_17,
122         OSM_INDEX_18,
123         NULL };
124
125 /* Cache hash tables */
126 struct osm_place_cache {
127         GHashTable *cache;
128         guint hit;
129         guint miss;
130 };
131 static struct osm_place_cache pcache;
132
133 static guint way_dist_range=OSM_RANGE_WAY;
134 static gint sid=0;
135
136 osm_way_node *osm_way_get_prev_node(osm_way *w);
137 osm_way_node *osm_way_get_next_node(osm_way *w);
138
139 /*****************************************************************************/
140
141 gboolean
142 osm_db_create(sqlite3 *db)
143 {
144 return db_exec_sql_array(db, osm_tables) && db_exec_sql_array(db, osm_indexes);
145 }
146
147 /*****************************************************************************/
148
149 void
150 osm_set_way_range(guint sr)
151 {
152 way_dist_range=sr;
153 g_debug("way_range set to %d", sr);
154 }
155
156 void
157 osm_set_way_range_from_speed(gfloat speed)
158 {
159 osm_set_way_range(speed>54.0 ? OSM_RANGE_WAY : (OSM_RANGE_WAY-lrint((speed/4)*1000)));
160 }
161
162 /*****************************************************************************/
163
164 static gboolean
165 osm_progress_pulse(void)
166 {
167 if (!dbpw)
168         return FALSE;
169 gtk_progress_bar_pulse(dbpw);
170 return TRUE;
171 }
172
173 static int
174 osm_progress(void *ud)
175 {
176 g_debug("SQL: Running gtk mainloop");
177 #if 1
178 while (gtk_events_pending())
179         gtk_main_iteration();
180 #else
181 gtk_main_iteration_do(FALSE);
182 #endif
183 return 0;
184 }
185
186 static void
187 osm_progress_hide(sqlite3 *db)
188 {
189 if (!dbpw)
190         return;
191 gtk_progress_bar_set_text(dbpw, "");
192 gtk_progress_bar_set_fraction(dbpw, 0.0);
193 }
194
195 static void
196 osm_progress_show(sqlite3 *db)
197 {
198 if (!dbpw)
199         return;
200 gtk_progress_bar_set_text(dbpw, _("Searching..."));
201 gtk_progress_bar_pulse(dbpw);
202 gtk_main_iteration_do(FALSE);
203 }
204
205 void
206 osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
207 {
208 if (dbpw!=NULL && w==NULL) {
209         osm_progress_hide(db);
210         if (sid!=0)
211                 g_source_remove(sid);
212         sid=0;
213         dbpw=NULL;
214         return;
215 }
216 dbpw=w;
217 if (w!=NULL) {
218         osm_progress_show(db);
219         sid=g_timeout_add(330, (GSourceFunc)osm_progress_pulse, NULL);
220 }
221 }
222
223 /*****************************************************************************/
224
225 static gboolean
226 osm_db_prepare(sqlite3 *db)
227 {
228 /*****************
229  * Place queries *
230  *****************/
231
232 /* Select nearest place inside lat,lon+-range */
233 DB_PREP(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
234                                         " ilat,ilon,places.nid,isin_p,isin_c "
235                                         " from places,nodes where type=$TYPE "
236                                         " and nodes.nid=places.nid "
237                                         " and ilat between $LAT-$RANGE and $LAT+$RANGE "
238                                         " and ilon between $LON-$RANGE and $LON+$RANGE "
239                                         " order by d limit 1", 
240                                         sql.select_place_near);
241
242 /* Select place name, distance, location, parent-place and type with given ID */
243 DB_PREP(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
244                                         " ilat,ilon,type,isin_p,isin_c "
245                                         " from places,nodes where "
246                                         " nodes.nid=places.nid "
247                                         " and places.nid=$NID order by d limit 1",
248                                         sql.select_place);
249
250 /* Search place names */
251 DB_PREP(db, "select places.nid,name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
252                                         " rlat,rlon,type,isin_p,isin_c "
253                                         " from places,nodes where "
254                                         " nodes.nid=places.nid "
255                                         " and name like $NAME order by d limit 200",
256                                         sql.select_place_search);
257
258 /***********************
259  * Way related queries *
260  ***********************/
261
262 /* Select nearest ways inside lat,lon+-range */
263 DB_PREP(db, "select w.wid,type,nodes,flags,"
264                                         "(($LAT-n.ilat)*($LAT-n.ilat))+(($LON-n.ilon)*($LON-n.ilon)) as d,wn.f,wn.t,n.ilat,n.ilon "
265                                         " from way as w,way_n2n as wn,nodes as n "
266                                         " where w.wid=wn.wid and wn.f=n.nid "
267                                         " and n.ilat between $LAT-$RANGE and $LAT+$RANGE "
268                                         " and n.ilon between $LON-$RANGE and $LON+$RANGE "
269                                         " and w.type between $WTS and $WTY " 
270                                         " order by d",
271                                         sql.select_way2);
272
273 /* Search way names inside bbox, using both primary and secondary language names */
274 DB_PREP(db, "select w.wid,w.name as name,"
275                                         "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
276                                         " from way_names as w,way as ww where "
277                                         " ww.type between $WTS and $WTY and w.wid=ww.wid and w.name like $NAME "
278                                         " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
279                                         " and ww.lon between $LON-$RANGE and $LON+$RANGE "
280                                         " union "
281                                         " select w.wid,n.name as name,"
282                                         "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
283                                         " from way_names as w, way as ww,way_names_nls as n on w.wid=n.wid where "
284                                         " ww.type between $WTS and $WTY and w.wid=ww.wid and n.name like $NAME "
285                                         " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
286                                         " and ww.lon between $LON-$RANGE and $LON+$RANGE "
287                                         " order by d, name limit 500",
288                                         sql.select_way_name_search);
289
290 /* Get way segment */
291 DB_PREP(db, "select wn.t,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=? and wn.t=nodes.nid limit 1",
292                     sql.select_way_next_seg);
293
294 /* Get way segment */
295 DB_PREP(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.t=? and wn.f=nodes.nid limit 1",
296                     sql.select_way_prev_seg);
297
298 /* Get Way name */
299 DB_PREP(db, "select name from way_names where wid=?", sql.select_way_name);
300
301 /* Get Way ref and int_ref */
302 DB_PREP(db, "select ref,int_ref from way_ref where rid=?", sql.select_way_ref);
303
304 /* Get way all way nodes */
305 DB_PREP(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=nodes.nid", sql.select_way_nodes);
306
307 /* Get next, prev node + way information. For routing. */
308 DB_PREP(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
309                         "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.f=?",
310                         sql.select_node_next);
311
312 DB_PREP(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
313                         "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.t=?",
314                     sql.select_node_prev);
315
316 return TRUE;
317 }
318
319 void
320 osm_deinit(void)
321 {
322 if (osmdb) {
323         if (sql.select_way_ref)
324                 sqlite3_finalize(sql.select_way_ref);
325         if (sql.select_way_name)
326                 sqlite3_finalize(sql.select_way_name);
327         if (sql.select_way_next_seg)
328                 sqlite3_finalize(sql.select_way_next_seg);
329         if (sql.select_way_prev_seg)
330                 sqlite3_finalize(sql.select_way_prev_seg);
331         if (sql.select_way_name_search)
332                 sqlite3_finalize(sql.select_way_name_search);
333         if (sql.select_way2)
334                 sqlite3_finalize(sql.select_way2);
335         if (sql.select_place)
336                 sqlite3_finalize(sql.select_place);
337         if (sql.select_place_near)
338                 sqlite3_finalize(sql.select_place_near);
339         if (sql.select_node_next)
340                 sqlite3_finalize(sql.select_node_next);
341         if (sql.select_node_prev)
342                 sqlite3_finalize(sql.select_node_prev);
343 }
344 osmdb=NULL;
345 osm_db_ok=FALSE;
346 memset(&sql, 0, sizeof(sql));
347 g_hash_table_destroy(pcache.cache);
348 pcache.cache=NULL;
349 pcache.hit=0;
350 pcache.miss=0;
351 g_timer_destroy(dbt);
352 }
353
354 gboolean
355 osm_init(sqlite3 **db)
356 {
357 osm_db_ok=FALSE;
358 pcache.cache=g_hash_table_new(g_direct_hash, g_direct_equal);
359 dbt=g_timer_new();
360
361 if (!db || !*db) {
362         osmdb=NULL;
363         return FALSE;
364 }
365
366 osmdb=*db;
367 memset(&sql, 0, sizeof(sql));
368 if (osm_db_create(osmdb)==FALSE) {
369         g_printerr("Failed to create OSM tables or indexes: %s", sqlite3_errmsg(osmdb));
370         return FALSE;
371 }
372
373 if (osm_db_prepare(osmdb)==FALSE) {
374         g_printerr("Failed to prepare OSM SQL statements: %s", sqlite3_errmsg(osmdb));
375         return FALSE;
376 }
377 osm_db_ok=TRUE;
378 return TRUE;
379 }
380
381 void
382 osm_db_enable_mainloop(sqlite3 *db, gboolean eml)
383 {
384 if (eml==FALSE)
385         sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
386 else
387         sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
388 }
389
390 /*****************************************************************************/
391
392 osm_way_node *
393 osm_way_node_new(guint id, gint lat, gint lon, gint flags)
394 {
395 osm_way_node *n=g_slice_new(osm_way_node);
396
397 n->id=id;
398 n->lat=lat;
399 n->lon=lon;
400 n->flags=flags;
401 return n;
402 }
403
404 void
405 osm_way_node_free(osm_way_node *n)
406 {
407 if (n)
408         g_slice_free(osm_way_node, n);
409 }
410
411 /**
412  * Free way nodes list 
413  */
414 void
415 osm_way_nodes_free(osm_way *w)
416 {
417 GList *iter;
418
419 if (!w->nodes) 
420         return;
421
422 for (iter=w->nodes; iter!=NULL; iter=iter->next)
423         g_slice_free(osm_way_node, (osm_way_node*)iter->data);
424
425 g_list_free(w->nodes);
426 }
427
428 /**
429  * Free a osm_way structure
430  */
431 void
432 osm_way_free(osm_way *w)
433 {
434 if (!w)
435         return;
436 osm_way_nodes_free(w);
437 if (w->name)
438         g_free(w->name);
439 if (w->ref)
440         g_free(w->ref);
441 if (w->int_ref)
442         g_free(w->int_ref);
443 g_slice_free(osm_way, w);
444 }
445
446 /*****************************************************************************/
447
448 static void
449 osm_place_free(osm_place *p)
450 {
451 if (p->name)
452         g_free(p->name);
453 g_slice_free(osm_place, p);
454 }
455
456 static gboolean
457 osm_place_remove(gpointer k, gpointer v, gpointer ud)
458 {
459 osm_place_free((osm_place *)v);
460 return TRUE;
461 }
462
463 static osm_place *
464 osm_place_new(void)
465 {
466 return g_slice_new0(osm_place);
467 }
468
469 static osm_place *
470 osm_place_cache_lookup(guint32 id)
471 {
472 osm_place *r;
473 r=g_hash_table_lookup(pcache.cache, GINT_TO_POINTER(id));
474 if (r) 
475         pcache.hit++; 
476 else 
477         pcache.miss++;
478
479 g_debug("OSM: Cache %d/%d", pcache.hit, pcache.miss);
480 return r;
481 }
482
483 static void
484 osm_place_cache_add(osm_place *p)
485 {
486 if (osm_place_cache_lookup(p->id)==NULL)
487         g_hash_table_insert(pcache.cache, GINT_TO_POINTER(p->id), p);
488 }
489
490 static void
491 osm_place_cache_gc(void)
492 {
493 guint r;
494
495 r=g_hash_table_foreach_remove(pcache.cache, osm_place_remove, NULL);
496 g_debug("OSM: Cache cleared (%d)", r);
497 pcache.hit=0;
498 pcache.miss=0;
499 }
500
501 static void
502 osm_place_update_distance(osm_place *p, gint lat, gint lon)
503 {
504 gdouble lam, lom;
505
506 lam=(gdouble)((lat-p->lat)*(lat-p->lat));
507 lom=(gdouble)((lon-p->lon)*(lon-p->lon));
508
509 p->dist=sqrt(lam+lom);
510 }
511
512 /**
513  * Get place with given id and distance to current location
514  */
515 gboolean
516 osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr)
517 {
518 osm_place *n;
519
520 g_return_val_if_fail(sql.select_place, FALSE);
521
522 n=*nr;
523 n=osm_place_cache_lookup(id);
524 if (n) {
525         osm_place_update_distance(n, lat, lon);
526         return TRUE;
527 }
528 n=NULL;
529
530 /* XXX: better place for this */
531 if (g_hash_table_size(pcache.cache)>OSM_PLACE_CACHE_MAX_ITEMS)
532         osm_place_cache_gc();
533
534 sqlite3_clear_bindings(sql.select_place);
535 sqlite3_reset(sql.select_place);
536
537 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
538     SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
539     SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
540         g_warning("Failed to bind values for place");
541         return FALSE;
542 }
543
544 QT_START
545 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
546         const gchar *place;
547         guint32 dist;
548
549         n=osm_place_new();
550         place=sqlite3_column_text(sql.select_place, 0);
551         n->name=g_strdup(place);
552         dist=sqlite3_column_int(sql.select_place, 1);
553         n->dist=sqrt((double)dist);
554         n->lat=sqlite3_column_int(sql.select_place, 2);
555         n->lon=sqlite3_column_int(sql.select_place, 3);
556         n->type=sqlite3_column_int(sql.select_place, 4);
557         n->isin_p=sqlite3_column_int(sql.select_place, 5);
558 /*      n->isin_c=sqlite3_column_int(sql.select_place, 6); */
559         return TRUE;
560 }
561 QT_END
562 return FALSE;
563 }
564
565 /**
566  * Search for the nearest place with given type
567  */
568 gboolean
569 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
570 {
571 gint range;
572 osm_place *n=NULL;
573
574 g_return_val_if_fail(sql.select_place_near, FALSE);
575
576 switch (type) {
577         case NODE_PLACE_SUBURB:
578                 range=95000;
579         break;
580         case NODE_PLACE_CITY:
581         case NODE_PLACE_TOWN:
582                 range=250000;
583         break;
584         case NODE_PLACE_HAMLET:
585         case NODE_PLACE_VILLAGE:
586                 range=100000;
587         break;
588         default:
589                 range=90000;
590         break;
591 }
592
593 sqlite3_clear_bindings(sql.select_place_near);
594 sqlite3_reset(sql.select_place_near);
595
596 if (SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 1, lat) ||
597     SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 2, lon) ||
598     SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 3, type) ||
599     SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 4, range)) {
600         g_warning("Failed to bind values for near place");
601         return FALSE;
602 }
603
604 n=osm_place_new();
605 n->isin_p=n->lat=n->lon=n->dist=0;
606 QT_START
607 if (SQLITE_ROW == sqlite3_step(sql.select_place_near)) {
608         const gchar *place;
609         guint32 dist;
610
611         place=sqlite3_column_text(sql.select_place_near, 0);
612         n->name=g_strdup(place);
613         dist=sqlite3_column_int(sql.select_place_near, 1);
614         n->dist=sqrt((double)dist);
615         n->lat=sqlite3_column_int(sql.select_place_near, 2);
616         n->lon=sqlite3_column_int(sql.select_place_near, 3);
617         n->id=sqlite3_column_int(sql.select_place_near, 4);
618         n->isin_p=sqlite3_column_int(sql.select_place_near, 5);
619 /*      n->isin_c=sqlite3_column_int(sql.select_place_near, 6); */
620         n->type=type;
621
622         QT_END
623         osm_place_cache_add(n);
624
625         *nr=n;
626         return TRUE;
627 }
628 *nr=n;
629 return FALSE;
630 }
631
632 /*
633  * Way helper 
634  *
635  */
636 static GList *
637 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
638 {
639 GList *ways=NULL;
640 osm_way *w;
641 guint wc=0;
642
643 g_return_val_if_fail(sql.select_way2, NULL);
644
645 sqlite3_reset(sql.select_way2);
646 sqlite3_clear_bindings(sql.select_way2);
647
648 if (SQLITE_OK != sqlite3_bind_int(sql.select_way2, 1, lat) ||
649     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 2, lon) ||
650     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 3, range) ||
651     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 4, WAY_ROAD_START) ||
652     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 5, WAY_ROAD_END)) {
653         g_warning("Failed to bind values for way");
654         return NULL;
655 }
656
657 QT_START
658 while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
659         guint32 dist;
660         gint lat, lon;
661
662         wc++;
663         w=g_slice_new0(osm_way);
664         w->id=sqlite3_column_int(sql.select_way2, 0);
665         w->type=sqlite3_column_int(sql.select_way2, 1);
666         w->nodecnt=sqlite3_column_int(sql.select_way2, 2);
667         w->flags=sqlite3_column_int(sql.select_way2, 3);
668         dist=sqlite3_column_int(sql.select_way2, 4);
669         w->dist=sqrt((gdouble)dist);
670         w->f=sqlite3_column_int(sql.select_way2, 5);
671         w->t=sqlite3_column_int(sql.select_way2, 6);
672
673         lat=sqlite3_column_int(sql.select_way2, 7);
674         lon=sqlite3_column_int(sql.select_way2, 8);
675
676         w->node_f=osm_way_node_new(w->f, lat, lon, 0);
677
678         ways=g_list_prepend(ways, w);
679 }
680 QT_END
681
682 return ways;
683 }
684
685 /*****************************************************************************/
686
687 GSList *
688 osm_get_route_node(guint nid, osm_node_direction d)
689 {
690 GSList *r=NULL;
691 osm_way *w;
692 guint wc=0;
693 sqlite3_stmt *psql=NULL;
694
695 g_return_val_if_fail(sql.select_node_next, FALSE);
696 g_return_val_if_fail(sql.select_node_prev, FALSE);
697
698 switch (d) {
699         case OSM_NODE_NEXT:
700                 psql=sql.select_node_next;
701         break;
702         case OSM_NODE_PREV:
703                 psql=sql.select_node_prev;
704         break;
705         default:
706                 g_assert_not_reached();
707         break;
708 }
709
710 sqlite3_reset(psql);
711 sqlite3_clear_bindings(psql);
712
713 if (SQLITE_OK != sqlite3_bind_int(psql, 1, nid)) {
714         g_warning("Failed to bind values for route node");
715         return NULL;
716 }
717
718 while (SQLITE_ROW == sqlite3_step(psql)) {
719         gdouble lat, lon;
720
721         wc++;
722         w=g_slice_new0(osm_way);
723         w->id=sqlite3_column_int(psql, 0);
724         w->type=sqlite3_column_int(psql, 1);
725         w->flags=sqlite3_column_int(psql, 2);
726         w->speed=sqlite3_column_int(psql, 3);
727
728         lat=sqlite3_column_double(psql, 5);
729         lon=sqlite3_column_double(psql, 6);
730
731         w->f=sqlite3_column_int(psql, 7);
732         w->t=sqlite3_column_int(psql, 8);
733 #if 0
734         w->node=
735         w->node->flags=sqlite3_column_int(psql, 9);
736         w->node->links=sqlite3_column_int(psql, 10);
737 #endif
738
739         r=g_slist_prepend(r, w);
740 }
741
742 return r;
743 }
744
745
746 /*****************************************************************************/
747 gboolean 
748 osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
749 {
750 if (!f) {
751         return FALSE;
752 }
753
754 if (!t) {
755         return FALSE;
756 }
757
758 return distance_point_to_line((gdouble)lon, (gdouble)lat, (gdouble)f->lon, (gdouble)f->lat, (gdouble)t->lon, (gdouble)t->lat, d);
759 }
760
761 /**
762  * Search for the nearest way (road)
763  * - First search for ways with nearest node
764  * - If only one is returned then we are done.
765  * - If more than one, go trough the results:
766  *   - Load nodes for the way, check prev/next nodes
767  *   - Store result if closer than before
768  * - Return closest way
769  */
770
771 #define START_DIST (900000.0)
772
773 osm_way *
774 osm_find_nearest_way(gint lat, gint lon)
775 {
776 GList *iter;
777 GList *w=NULL;
778 guint range=OSM_RANGE_START;
779 osm_way *cw=NULL;
780 guint found_ways=0;
781 gdouble pdist=START_DIST, dist_n, dist_p;
782
783 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=OSM_RANGE_STOP) {
784         range+=OSM_RANGE_STEP;
785         g_debug("Trying with range: %d", range);
786 }
787 found_ways=g_list_length(w);
788 g_debug("Found %d ways withing range %d", found_ways, range);
789
790 if (found_ways==0)
791         return NULL;
792
793 for (iter=w; iter!=NULL; iter=iter->next) {
794         osm_way_node *wnn;
795         osm_way_node *wnp;
796         osm_way *way=(osm_way*)iter->data;
797
798         way->node_t=NULL;
799
800         wnn=osm_way_get_next_node(way);
801         if (osm_way_distance(lat, lon, way->node_f, wnn, &dist_n)==FALSE) {
802                 osm_way_node_free(wnn);
803                 dist_n=START_DIST;
804         } else if (dist_n<pdist) { /* Is it near ?*/
805                 pdist=dist_n;
806                 cw=way;
807                 way->distance=dist_n;
808                 way->node_t=wnn;
809         } else {
810                 dist_n=START_DIST;
811         }
812
813         g_debug("WayN: #%d (T:%d), %d nodes, near [%d-%d], D: %.2f (Valid: %s)",
814                 way->id, way->type, way->nodecnt, way->f, way->t, dist_n, dist_n==START_DIST ? "F" : "T");
815
816         wnp=osm_way_get_prev_node(way);
817         if (osm_way_distance(lat, lon, way->node_f, wnp, &dist_p)==FALSE) {
818                 osm_way_node_free(wnp);
819                 dist_p=START_DIST;
820         } else if (dist_p<pdist) {
821                 pdist=dist_p;
822                 cw=way;
823                 way->distance=dist_n;
824                 if (way->node_t) {
825                         osm_way_node_free(wnn);
826                 }
827                 way->node_t=wnp;
828         } else {
829                 dist_p=START_DIST;
830         }
831
832         g_debug("WayP: #%d (T:%d), %d nodes, near [%d-%d], D: %.2f (Valid: %s)",
833                 way->id, way->type, way->nodecnt, way->f, way->t, dist_p, dist_p==START_DIST ? "F" : "T");
834
835         if (!cw) {
836                 osm_way_free(way);
837                 way=NULL;
838         }
839 }
840
841 g_list_free(w);
842 if (cw==NULL)
843         return NULL;
844
845 osm_way_get_name(cw);
846 if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK || 
847         cw->type==WAY_PRIMARY  || cw->type==WAY_SECONDARY || cw->type==WAY_TERTIARY) {
848                 osm_way_get_ref(cw);
849 }
850 osm_way_get_nodes(cw);
851
852 g_debug("Found: (#%d): [%s]:[%s][%s]", cw->id, cw->name, cw->ref, cw->int_ref);
853 g_debug("T: %d F: %d N#: %d D: %.2f", cw->type, cw->flags, cw->nodecnt, cw->dist);
854 g_debug("NF#: %d NT#: %d (DC: %.2f)", cw->f, cw->t, cw->distance);
855
856 return cw;
857 }
858
859 /* XXX: These two should be combined to save memory */
860 /**
861  * Get previous node/segment of given way node
862  *
863  */
864 osm_way_node *
865 osm_way_get_prev_node(osm_way *w)
866 {
867 g_return_val_if_fail(sql.select_way_prev_seg, NULL);
868
869 sqlite3_reset(sql.select_way_prev_seg);
870 sqlite3_clear_bindings(sql.select_way_prev_seg);
871
872 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 1, w->id) ||
873         SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 2, w->f)  ) {
874         g_warning("Failed to bind values for prev seg");
875         return NULL;
876 }
877
878 if (SQLITE_ROW == sqlite3_step(sql.select_way_prev_seg)) {
879         return osm_way_node_new(
880                 sqlite3_column_int(sql.select_way_prev_seg, 0),
881                 sqlite3_column_int(sql.select_way_prev_seg, 1),
882                 sqlite3_column_int(sql.select_way_prev_seg, 2),
883                 0);
884 }
885
886 return NULL;
887 }
888
889 /**
890  * Get next node/segment of given way node
891  *
892  */
893 osm_way_node *
894 osm_way_get_next_node(osm_way *w)
895 {
896 g_return_val_if_fail(sql.select_way_next_seg, NULL);
897
898 sqlite3_reset(sql.select_way_next_seg);
899 sqlite3_clear_bindings(sql.select_way_next_seg);
900
901 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 1, w->id) ||
902         SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 2, w->f)  ) {
903         g_warning("Failed to bind values for next seg");
904         return NULL;
905 }
906
907 if (SQLITE_ROW == sqlite3_step(sql.select_way_next_seg)) {
908         return osm_way_node_new(
909                 sqlite3_column_int(sql.select_way_next_seg, 0),
910                 sqlite3_column_int(sql.select_way_next_seg, 1),
911                 sqlite3_column_int(sql.select_way_next_seg, 2),
912                 0);
913 }
914
915 return NULL;
916 }
917
918 /**
919  * Get list of nodes for given way
920  *
921  */
922 gboolean
923 osm_way_get_nodes(osm_way *w)
924 {
925 if (w->nodes!=NULL)
926         return TRUE;
927
928 g_return_val_if_fail(sql.select_way_nodes, FALSE);
929
930 sqlite3_reset(sql.select_way_nodes);
931 sqlite3_clear_bindings(sql.select_way_nodes);
932
933 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
934         g_warning("Failed to bind values for way nodes");
935         return FALSE;
936 }
937
938 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
939         osm_way_node *n;
940
941         n=g_slice_new(osm_way_node);
942         n->id=sqlite3_column_int(sql.select_way_nodes, 0);
943         n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
944         n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
945         w->nodes=g_list_append(w->nodes, n);
946 }
947
948 return (w->nodes==NULL) ? FALSE : TRUE;
949 }
950
951 /**
952  * Get way name
953  *
954  */
955 gboolean
956 osm_way_get_name(osm_way *w)
957 {
958 g_return_val_if_fail(sql.select_way_name, FALSE);
959
960 sqlite3_reset(sql.select_way_name);
961 sqlite3_clear_bindings(sql.select_way_name);
962
963 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
964         g_warning("Failed to bind values for way name");
965         return FALSE;
966 }
967
968 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
969         const gchar *place;
970         place=sqlite3_column_text(sql.select_way_name, 0);
971         w->name=g_strdup(place);
972 }
973 return FALSE;
974 }
975
976 #if 0
977 gboolean
978 osm_way_get_name_nls(osm_way *w)
979 {
980 g_return_val_if_fail(sql.select_way_name_nls, FALSE);
981
982 sqlite3_reset(sql.select_way_name_nls);
983 sqlite3_clear_bindings(sql.select_way_name_nls);
984
985 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
986         SQLITE_OK != sqlite3_bind_) {
987         g_warning("Failed to bind values for way name nls");
988         return FALSE;
989 }
990
991 if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
992         const gchar *place;
993         place=sqlite3_column_text(sql.select_way_name_nls, 0);
994         w->name=g_strdup(place);
995 }
996 return FALSE;
997 }
998 #endif
999
1000
1001 /**
1002  * Get Way ref and int_ref
1003  *
1004  */
1005 gboolean
1006 osm_way_get_ref(osm_way *w)
1007 {
1008 g_return_val_if_fail(sql.select_way_ref, FALSE);
1009
1010 sqlite3_reset(sql.select_way_ref);
1011 sqlite3_clear_bindings(sql.select_way_ref);
1012
1013 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
1014         g_warning("Failed to bind values for way ref");
1015         return FALSE;
1016 }
1017
1018 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
1019         const gchar *ref, *int_ref;
1020         ref=sqlite3_column_text(sql.select_way_ref, 0);
1021         int_ref=sqlite3_column_text(sql.select_way_ref, 1);
1022         w->ref=g_strdup(ref);
1023         w->int_ref=g_strdup(int_ref);
1024 }
1025 return FALSE;
1026 }
1027
1028 /******************************************************************************/
1029
1030 /**
1031  * Check if we have moved away from the last known street
1032  */
1033 gboolean
1034 osm_check_location(osm_location *map_loc, gint lat, gint lon)
1035 {
1036 gdouble dist;
1037 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
1038         return (dist>(gdouble)way_dist_range) ? FALSE : TRUE;
1039 } else
1040         return FALSE;
1041 }
1042
1043 /**
1044  * Try to figure out where the given lat,lon is. Fills in the given struct,
1045  * with street, secondary (suburb) and primary (city,town,village) location.
1046  * Will try to minimize the amount of database access by skipping queries
1047  * if we haven't moved or if we don't know where we are.
1048  *
1049  */
1050 gboolean 
1051 osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc)
1052 {
1053 gdouble dist;
1054 gboolean check_place=FALSE;
1055 gulong d;
1056
1057 /* Check 10 times, if location is not known then assume we are in here-be-dragons land */
1058 if (map_loc->nfcnt>10) {
1059         time_t t;
1060         t=time(NULL)-map_loc->last_valid; 
1061         if (t<30) {
1062                 g_debug("Here be dragons");
1063                 return FALSE;
1064         } else {
1065                 g_debug("Trying again");
1066                 map_loc->last_valid=time(NULL);
1067                 map_loc->nfcnt=0;
1068                 map_loc->valid=FALSE;
1069         }
1070 }
1071
1072 if (map_loc->valid==FALSE) {
1073         map_loc->lat=lat;
1074         map_loc->lon=lon;
1075         map_loc->valid=TRUE;
1076         d=way_dist_range*5;
1077 } else {
1078         d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
1079 }
1080
1081 /* Check if we are still near the same way as last time */
1082 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
1083         /* We are probably on the same way as last time, 
1084            but check if the distance is over a limit or our heading has changed significantly.
1085      */
1086         if ( (dist>(gdouble)way_dist_range) || (fabs(angle_diff(heading, map_loc->heading))>15.0)) {
1087                 /* We have moved a large amount, check way again */
1088                 g_debug("Distance %.2f > %.2f range or angle %f > 15.0, checking location", 
1089                         dist, (gdouble)way_dist_range, fabs(heading-map_loc->heading));
1090                 osm_way_free(map_loc->street);
1091                 map_loc->street=osm_find_nearest_way(lat, lon);
1092                 check_place=TRUE;
1093                 map_loc->changed=TRUE;
1094         } else {
1095                 g_debug("*** No change in location: %f %d", dist, way_dist_range);
1096                 /* We are still on the same way as last time */
1097                 check_place=FALSE;
1098                 map_loc->changed=FALSE;
1099         }
1100         map_loc->lat=lat;
1101         map_loc->lon=lon;
1102 } else {
1103         /* We didn't know our location, so check it, but only if we have moved */
1104         if (d>way_dist_range) {
1105                 g_debug("*** Must check location");
1106                 check_place=TRUE;
1107                 osm_way_free(map_loc->street);
1108                 map_loc->street=osm_find_nearest_way(lat, lon);
1109 #if 0
1110                 map_loc->lat=lat;
1111                 map_loc->lon=lon;
1112 #endif
1113         } 
1114
1115         if (!map_loc->street) {
1116                 g_debug("*** Street not known");
1117                 map_loc->nfcnt++;
1118                 map_loc->changed=TRUE;
1119         } else {
1120                 g_debug("*** Street known");
1121                 map_loc->nfcnt=0;
1122                 map_loc->last_valid=time(NULL);
1123                 map_loc->changed=TRUE;
1124                 check_place=TRUE;
1125         }
1126 }
1127
1128 if (map_loc->changed==TRUE) {
1129         map_loc->heading=heading;
1130 }
1131
1132 g_debug("NotFoundCounter: %d", map_loc->nfcnt);
1133 g_debug("D: %ld %ld", d, (gulong)way_dist_range);
1134
1135 if (check_place==TRUE || d>way_dist_range*4) {
1136         gboolean fs;
1137
1138         fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
1139         if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin_p!=0) {
1140                 if (osm_place_get(map_loc->secondary->isin_p, lat, lon, &(map_loc->primary))==FALSE) {
1141                         if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1142                                 g_debug("Near city: %s", map_loc->primary->name);
1143                         else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1144                                 g_debug("Near town: %s", map_loc->primary->name);
1145                         else {
1146                                 g_assert(map_loc->primary!=NULL);
1147                                 g_debug("Unknown");
1148                         }
1149                 } else {
1150                         g_debug("In: %s", map_loc->primary ? map_loc->primary->name : "?");
1151                 }
1152         } else if (map_loc->street && map_loc->street->isin_p!=0) {
1153                 if (osm_place_get(map_loc->street->isin_p, lat, lon, &map_loc->primary)==FALSE) {
1154                         g_debug("Street location not know.");
1155                 } else {
1156                         g_debug("Street is in: %s", map_loc->primary ? map_loc->primary->name : "?");
1157                 }
1158         } else {
1159                 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1160                         g_debug("Near city: %s", map_loc->primary->name);
1161                 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1162                         g_debug("Near town: %s", map_loc->primary->name);
1163                 else {
1164                         g_assert(map_loc->primary!=NULL);
1165                         g_debug("Unknown");
1166                 }
1167         }
1168 }
1169
1170 return map_loc->street ? TRUE : FALSE;
1171 }
1172
1173 /**
1174  * osm_place_search
1175  */
1176 gboolean
1177 osm_place_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
1178 {
1179 GtkTreeIter iter;
1180 gchar *ltext=NULL;
1181 guint rows=0;
1182 gchar tmp1[16], tmp2[16];
1183 gdouble range=6;
1184
1185 g_return_val_if_fail(sql.select_place_search, FALSE);
1186 g_return_val_if_fail(text, FALSE);
1187
1188 ltext=g_strdup_printf("%s%%", text);
1189
1190 if (SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 1, lat) ||
1191     SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 2, lon) ||
1192         SQLITE_OK != sqlite3_bind_text(sql.select_place_search,   3, ltext, -1, SQLITE_TRANSIENT)) {
1193                 g_warning("Failed to bind values for sql.select_place_search");
1194                 sqlite3_clear_bindings(sql.select_place_search);
1195                 g_free(ltext);
1196                 return FALSE;
1197 }
1198
1199 if (ltext)
1200         g_free(ltext);
1201
1202 *store = gtk_list_store_new(ITEM_NUM_COLUMNS, 
1203                                 G_TYPE_INT,             /* ID */
1204                                 G_TYPE_INT,             /*  */
1205                                 G_TYPE_DOUBLE,  /* Latitude */
1206                                 G_TYPE_DOUBLE,  /* Longitude */
1207                                 G_TYPE_DOUBLE,  /* Distance */
1208                                 G_TYPE_STRING,  /* Lat/Lon */
1209                                 G_TYPE_STRING,  /* Label */
1210                                 G_TYPE_STRING,  /* Desc. */
1211                                 G_TYPE_STRING,  /* Category */
1212                                 G_TYPE_STRING,  /* Dummy */
1213                                 G_TYPE_STRING); /* Dummy */
1214
1215 while (SQLITE_ROW == sqlite3_step(sql.select_place_search)) {
1216         gdouble rlat, rlon, dist;
1217
1218         rlat=sqlite3_column_double(sql.select_place_search, 3);
1219         rlon=sqlite3_column_double(sql.select_place_search, 4);
1220         lat_format(_degformat, rlat, tmp1);
1221         lon_format(_degformat, rlon, tmp2);
1222         dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
1223
1224         gtk_list_store_append(*store, &iter);
1225         gtk_list_store_set(*store, &iter,
1226                 ITEM_ID, sqlite3_column_int(sql.select_place_search, 0),
1227                 ITEM_LAT, rlat,
1228                 ITEM_LON, rlon,
1229                 ITEM_DIST, dist,
1230                 ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
1231                 ITEM_LABEL, sqlite3_column_text(sql.select_place_search, 1),
1232                 -1);
1233         rows++;
1234 }
1235
1236 g_debug("Found: %d places", rows);
1237
1238 sqlite3_reset(sql.select_place_search);
1239 sqlite3_clear_bindings(sql.select_place_search);
1240
1241 return TRUE;
1242 }
1243
1244 /**
1245  * osm_way_search
1246  *
1247  * Search for a street(way) starting with given 'text', next given lat/lon
1248  *
1249  */
1250 gboolean
1251 osm_way_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
1252 {
1253 GtkTreeIter iter;
1254 gchar *ltext=NULL;
1255 guint rows=0;
1256 gchar tmp1[16], tmp2[16];
1257 gdouble range=6;
1258
1259 g_return_val_if_fail(sql.select_way_name_search, FALSE);
1260 g_return_val_if_fail(text, FALSE);
1261
1262 g_debug("Way Search: [%s] around %.6f %.6f", text, lat, lon);
1263
1264 ltext=g_strdup_printf("%s%%", text);
1265
1266 if (SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 1, lat) ||
1267     SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 2, lon) ||
1268     SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,    3, WAY_ROAD_START) ||
1269     SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,    4, WAY_ROAD_END) ||
1270     SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 6, range) ||
1271         SQLITE_OK != sqlite3_bind_text(sql.select_way_name_search,   5, ltext, -1, SQLITE_TRANSIENT)) {
1272                 g_warning("Failed to bind values for sql.select_way_name_search");
1273                 sqlite3_clear_bindings(sql.select_way_name_search);
1274                 g_free(ltext);
1275                 return FALSE;
1276 }
1277
1278 if (ltext)
1279         g_free(ltext);
1280
1281 *store = gtk_list_store_new(ITEM_NUM_COLUMNS, 
1282                                 G_TYPE_INT,             /* ID */
1283                                 G_TYPE_INT,             /*  */
1284                                 G_TYPE_DOUBLE,  /* Latitude */
1285                                 G_TYPE_DOUBLE,  /* Longitude */
1286                                 G_TYPE_DOUBLE,  /* Distance */
1287                                 G_TYPE_STRING,  /* Lat/Lon */
1288                                 G_TYPE_STRING,  /* Label */
1289                                 G_TYPE_STRING,  /* Desc. */
1290                                 G_TYPE_STRING,  /* Category */
1291                                 G_TYPE_STRING,  /* Dummy */
1292                                 G_TYPE_STRING); /* Dummy */
1293
1294 while (SQLITE_ROW == sqlite3_step(sql.select_way_name_search)) {
1295         gdouble rlat, rlon, dist;
1296
1297         rlat=sqlite3_column_double(sql.select_way_name_search, 3);
1298         rlon=sqlite3_column_double(sql.select_way_name_search, 4);
1299         lat_format(_degformat, rlat, tmp1);
1300         lon_format(_degformat, rlon, tmp2);
1301         dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
1302
1303         gtk_list_store_append(*store, &iter);
1304         gtk_list_store_set(*store, &iter,
1305                 ITEM_ID, sqlite3_column_int(sql.select_way_name_search, 0),
1306                 ITEM_LAT, rlat,
1307                 ITEM_LON, rlon,
1308                 ITEM_DIST, dist,
1309                 ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
1310                 ITEM_LABEL, sqlite3_column_text(sql.select_way_name_search, 1),
1311                 -1);
1312         rows++;
1313 }
1314
1315 g_debug("Found: %d items", rows);
1316
1317 sqlite3_reset(sql.select_way_name_search);
1318 sqlite3_clear_bindings(sql.select_way_name_search);
1319
1320 return TRUE;
1321 }