2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 #include "projection.h"
30 struct search_list_level {
32 struct search_list_common *parent;
36 struct mapset_search *search;
38 GList *list,*curr,*last;
44 struct search_list_level levels[4];
45 struct search_list_result result;
46 struct search_list_result last_result;
47 int last_result_valid;
51 search_item_hash_hash(gconstpointer key)
53 const struct item *itm=key;
54 gconstpointer hashkey=(gconstpointer)GINT_TO_POINTER(itm->id_hi^itm->id_lo);
55 return g_direct_hash(hashkey);
59 search_item_hash_equal(gconstpointer a, gconstpointer b)
61 const struct item *itm_a=a;
62 const struct item *itm_b=b;
63 if (item_is_equal_id(*itm_a, *itm_b))
69 search_list_new(struct mapset *ms)
71 struct search_list *ret;
73 ret=g_new0(struct search_list, 1);
79 static void search_list_search_free(struct search_list *sl, int level);
82 search_list_level(enum attr_type attr_type)
85 case attr_country_all:
87 case attr_country_iso2:
88 case attr_country_iso3:
89 case attr_country_car:
90 case attr_country_name:
92 case attr_town_postal:
95 case attr_district_name:
96 case attr_town_or_district_name:
98 case attr_street_name:
100 case attr_house_number:
103 dbg(0,"unknown search '%s'\n",attr_to_name(attr_type));
109 search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
111 struct search_list_level *le;
112 int level=search_list_level(search_attr->type);
113 dbg(1,"level=%d\n", level);
117 le=&this_->levels[level];
118 search_list_search_free(this_, level);
119 le->attr=attr_dup(search_attr);
122 le=&this_->levels[level-1];
125 dbg(1,"le=%p partial=%d\n", le, partial);
129 struct search_list_common *
130 search_list_select(struct search_list *this_, enum attr_type attr_type, int id, int mode)
132 int level=search_list_level(attr_type);
134 struct search_list_level *le;
135 struct search_list_common *slc;
137 le=&this_->levels[level];
141 dbg(1,"enter level=%d %d %d %p\n", level, id, mode, curr);
144 if (! id || num == id) {
153 curr=g_list_next(curr);
155 dbg(1,"not found\n");
160 search_list_common_new(struct item *item, struct search_list_common *common)
163 if (item_attr_get(item, attr_town_name, &attr))
164 common->town_name=map_convert_string(item->map, attr.u.str);
166 common->town_name=NULL;
167 if (item_attr_get(item, attr_district_name, &attr))
168 common->district_name=map_convert_string(item->map, attr.u.str);
170 common->district_name=NULL;
171 if (item_attr_get(item, attr_postal, &attr))
172 common->postal=map_convert_string(item->map, attr.u.str);
173 else if (item_attr_get(item, attr_town_postal, &attr))
174 common->postal=map_convert_string(item->map, attr.u.str);
177 if (item_attr_get(item, attr_postal_mask, &attr))
178 common->postal_mask=map_convert_string(item->map, attr.u.str);
180 common->postal_mask=NULL;
184 search_list_common_destroy(struct search_list_common *common)
186 map_convert_free(common->town_name);
187 map_convert_free(common->district_name);
188 map_convert_free(common->postal);
189 map_convert_free(common->postal_mask);
192 static struct search_list_country *
193 search_list_country_new(struct item *item)
195 struct search_list_country *ret=g_new0(struct search_list_country, 1);
198 ret->common.item=ret->common.unique=*item;
199 if (item_attr_get(item, attr_country_car, &attr))
200 ret->car=g_strdup(attr.u.str);
201 if (item_attr_get(item, attr_country_iso2, &attr)) {
202 ret->iso2=g_strdup(attr.u.str);
203 ret->flag=g_strdup_printf("country_%s", ret->iso2);
205 if (item_attr_get(item, attr_country_iso3, &attr))
206 ret->iso3=g_strdup(attr.u.str);
207 if (item_attr_get(item, attr_country_name, &attr))
208 ret->name=g_strdup(attr.u.str);
213 search_list_country_destroy(struct search_list_country *this_)
223 static struct search_list_town *
224 search_list_town_new(struct item *item)
226 struct search_list_town *ret=g_new0(struct search_list_town, 1);
231 ret->common.item=ret->common.unique=*item;
232 if (item_attr_get(item, attr_town_streets_item, &attr)) {
233 dbg(1,"town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo);
234 ret->common.unique=*attr.u.item;
236 search_list_common_new(item, &ret->common);
237 if (item_attr_get(item, attr_county_name, &attr))
238 ret->county=map_convert_string(item->map,attr.u.str);
241 if (item_coord_get(item, &c, 1)) {
242 ret->common.c=g_new(struct pcoord, 1);
243 ret->common.c->x=c.x;
244 ret->common.c->y=c.y;
245 ret->common.c->pro = map_projection(item->map);
251 search_list_town_destroy(struct search_list_town *this_)
253 map_convert_free(this_->county);
254 search_list_common_destroy(&this_->common);
256 g_free(this_->common.c);
261 static struct search_list_street *
262 search_list_street_new(struct item *item)
264 struct search_list_street *ret=g_new0(struct search_list_street, 1);
268 ret->common.item=ret->common.unique=*item;
269 if (item_attr_get(item, attr_street_name, &attr))
270 ret->name=map_convert_string(item->map, attr.u.str);
273 search_list_common_new(item, &ret->common);
274 if (item_coord_get(item, &c, 1)) {
275 ret->common.c=g_new(struct pcoord, 1);
276 ret->common.c->x=c.x;
277 ret->common.c->y=c.y;
278 ret->common.c->pro = map_projection(item->map);
285 search_list_street_destroy(struct search_list_street *this_)
287 map_convert_free(this_->name);
288 search_list_common_destroy(&this_->common);
290 g_free(this_->common.c);
294 static struct search_list_house_number *
295 search_list_house_number_new(struct item *item)
297 struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
301 ret->common.item=ret->common.unique=*item;
302 if (item_attr_get(item, attr_house_number, &attr))
303 ret->house_number=map_convert_string(item->map, attr.u.str);
304 search_list_common_new(item, &ret->common);
305 if (item_coord_get(item, &c, 1)) {
306 ret->common.c=g_new(struct pcoord, 1);
307 ret->common.c->x=c.x;
308 ret->common.c->y=c.y;
309 ret->common.c->pro = map_projection(item->map);
315 search_list_house_number_destroy(struct search_list_house_number *this_)
317 map_convert_free(this_->house_number);
318 search_list_common_destroy(&this_->common);
320 g_free(this_->common.c);
325 search_list_result_destroy(int level, void *p)
329 search_list_country_destroy(p);
332 search_list_town_destroy(p);
335 search_list_street_destroy(p);
338 search_list_house_number_destroy(p);
344 search_list_search_free(struct search_list *sl, int level)
346 struct search_list_level *le=&sl->levels[level];
349 mapset_search_destroy(le->search);
354 g_hash_table_destroy(le->hash);
360 search_list_result_destroy(level, curr->data);
361 next=g_list_next(curr);
365 g_list_free(le->list);
373 postal_merge(char *mask, char *new)
375 dbg(1,"enter %s %s\n", mask, new);
381 return g_strdup(new);
383 while (mask[i] && new[i]) {
384 if (mask[i] != '.' && mask[i] != new[i])
394 dbg(1,"merged %s with %s as %s\n", mask, new, ret);
399 search_add_result(struct search_list_level *le, struct search_list_common *slc)
401 struct search_list_common *slo;
403 slo=g_hash_table_lookup(le->hash, &slc->unique);
405 g_hash_table_insert(le->hash, &slc->unique, slc);
406 if (slc->postal && !slc->postal_mask) {
407 slc->postal_mask=g_strdup(slc->postal);
409 le->list=g_list_append(le->list, slc);
412 merged=postal_merge(slo->postal_mask, slc->postal);
414 g_free(slo->postal_mask);
415 slo->postal_mask=merged;
420 struct search_list_result *
421 search_list_get_result(struct search_list *this_)
423 struct search_list_level *le,*leu;
425 int level=this_->level;
428 le=&this_->levels[level];
429 dbg(1,"le=%p\n", le);
431 dbg(1,"le->search=%p\n", le->search);
433 dbg(1,"partial=%d level=%d\n", le->partial, level);
437 leu=&this_->levels[level-1];
438 dbg(1,"leu->curr=%p\n", leu->curr);
440 struct search_list_common *slc;
443 le->parent=leu->curr->data;
445 leu->curr=g_list_next(leu->curr);
446 slc=(struct search_list_common *)(le->parent);
449 if (slc->selected == leu->selected)
454 dbg(1,"mapset_search_new with item(%d,%d)\n", le->parent->item.id_hi, le->parent->item.id_lo);
455 dbg(1,"attr=%s\n", attr_to_name(le->attr->type));
456 le->search=mapset_search_new(this_->ms, &le->parent->item, le->attr, le->partial);
457 le->hash=g_hash_table_new(search_item_hash_hash, search_item_hash_equal);
459 dbg(1,"le->search=%p\n", le->search);
460 item=mapset_search_get_item(le->search);
461 dbg(1,"item=%p\n", item);
464 dbg(1,"id_hi=%d id_lo=%d\n", item->id_hi, item->id_lo);
465 this_->result.country=NULL;
466 this_->result.town=NULL;
467 this_->result.street=NULL;
468 this_->result.c=NULL;
471 p=search_list_country_new(item);
472 this_->result.country=p;
473 this_->result.country->common.parent=NULL;
476 p=search_list_town_new(item);
477 this_->result.town=p;
478 this_->result.town->common.parent=this_->levels[0].last->data;
479 this_->result.country=this_->result.town->common.parent;
480 this_->result.c=this_->result.town->common.c;
483 p=search_list_street_new(item);
484 this_->result.street=p;
485 this_->result.street->common.parent=this_->levels[1].last->data;
486 this_->result.town=this_->result.street->common.parent;
487 this_->result.country=this_->result.town->common.parent;
488 this_->result.c=this_->result.street->common.c;
491 p=search_list_house_number_new(item);
492 this_->result.house_number=p;
493 this_->result.house_number->common.parent=this_->levels[2].last->data;
494 this_->result.street=this_->result.house_number->common.parent;
495 this_->result.town=this_->result.street->common.parent;
496 this_->result.country=this_->result.town->common.parent;
497 this_->result.c=this_->result.house_number->common.c;
501 if (search_add_result(le, p)) {
503 return &this_->result;
505 search_list_result_destroy(level, p);
508 mapset_search_destroy(le->search);
510 g_hash_table_destroy(le->hash);
519 search_list_destroy(struct search_list *this_)
531 search_fix_spaces(char *str)
535 char c,*s,*d,*ret=g_strdup(str);
537 for (i = 0 ; i < len ; i++) {
538 if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
546 if (c != ' ' || len != 0) {
550 while (c == ' ' && *s == ' ')
552 if (c == ' ' && *s == '\0') {
561 search_split_phrases(char *str)
569 ret=g_list_append(ret, g_strdup(s));
573 ret=g_list_append(ret, g_strdup(tmp));
584 } while (*s != '\0');
585 } while (*s != '\0');
590 search_address_housenumber(struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, GList *exclude3)
592 struct search_list_result *slr;
596 attr.type=attr_street_name;
597 while (slr=search_list_get_result(sl)) {
599 dbg(0,"%p %p\n",slr->country,slr->town);
600 dbg(0,"%s %s %s %s %s\n",slr->country->car,slr->town->common.postal,slr->town->name,slr->town->district,slr->street->name);
605 dbg(0,"count %d\n",count);
607 if (tmp != exclude1 && tmp != exclude2 && tmp != exclude3) {
608 attr.type=attr_house_number;
609 attr.u.str=tmp->data;
610 search_list_search(sl, &attr, 0);
611 while (slr=search_list_get_result(sl)) {
612 dbg(0,"result %s %s(%s) %s %s\n",slr->house_number->common.postal,slr->house_number->common.town_name, slr->house_number->common.district_name,slr->street->name,slr->house_number->house_number);
616 tmp=g_list_next(tmp);
620 search_address_street(struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2)
622 struct search_list_result *slr;
626 attr.type=attr_street_name;
627 while (slr=search_list_get_result(sl)) {
629 dbg(0,"%s %s %s %s",slr->country->car,slr->town->name,slr->town->district,slr->street->name);
631 dbg(0,"%s %s %s %s\n",slr->country->car,slr->town->common.postal,slr->town->name,slr->town->district);
636 dbg(0,"count %d\n",count);
638 if (tmp != exclude1 && tmp != exclude2) {
639 attr.u.str=tmp->data;
640 search_list_search(sl, &attr, 0);
641 search_address_housenumber(sl, phrases, exclude1, exclude2, tmp);
643 tmp=g_list_next(tmp);
648 search_address_town(struct search_list *sl, GList *phrases, GList *exclude)
653 attr.type=attr_town_or_district_name;
654 while (search_list_get_result(sl))
658 dbg(0,"count %d\n",count);
660 if (tmp != exclude) {
661 attr.u.str=tmp->data;
662 search_list_search(sl, &attr, 0);
663 search_address_street(sl, phrases, exclude, tmp);
665 tmp=g_list_next(tmp);
670 search_by_address(struct mapset *ms, char *addr)
672 char *str=search_fix_spaces(addr);
673 GList *tmp,*phrases=search_split_phrases(str);
674 dbg(0,"enter %s\n",addr);
675 struct search_list *sl;
676 struct search_list_result *slr;
678 attr.type=attr_country_all;
680 sl=search_list_new(ms);
682 attr.u.str=tmp->data;
683 search_list_search(sl, &attr, 0);
684 search_address_town(sl, phrases, tmp);
685 tmp=g_list_next(tmp);
687 search_list_search(sl, country_default(), 0);
688 search_address_town(sl, phrases, NULL);