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.
25 #include "projection.h"
30 #include "transform.h"
33 #include "linguistics.h"
40 static struct search_list_result *search_list_result_dup(struct search_list_result *slr);
41 static void search_list_country_destroy(struct search_list_country *this_);
42 static void search_list_town_destroy(struct search_list_town *this_);
43 static void search_list_street_destroy(struct search_list_street *this_);
44 static void search_list_house_number_destroy(struct search_list_house_number *this_);
46 struct search_list_level {
48 struct search_list_common *parent;
52 struct mapset_search *search;
54 GList *list,*curr,*last;
57 struct interpolation {
59 char *first, *last, *curr;
66 struct search_list_level levels[4];
67 struct search_list_result result;
68 struct search_list_result last_result;
69 int last_result_valid;
71 struct interpolation inter;
72 int use_address_results;
73 GList *address_results,*address_results_pos;
77 search_item_hash_hash(gconstpointer key)
79 const struct item *itm=key;
80 gconstpointer hashkey=(gconstpointer)GINT_TO_POINTER(itm->id_hi^itm->id_lo);
81 return g_direct_hash(hashkey);
85 search_item_hash_equal(gconstpointer a, gconstpointer b)
87 const struct item *itm_a=a;
88 const struct item *itm_b=b;
89 if (item_is_equal_id(*itm_a, *itm_b))
95 * @brief Create new instance of search_list to run a search.
97 * @param ms mapset that is to be searched
98 * @returns new search_list
101 search_list_new(struct mapset *ms)
103 struct search_list *ret;
105 ret=g_new0(struct search_list, 1);
111 static void search_list_search_free(struct search_list *sl, int level);
114 * @brief Determine search list level for given attr_type.
115 * @param attr_type attribute value
116 * @return corresponding search list level (country=0, town=1, ...)
119 search_list_level(enum attr_type attr_type)
122 case attr_country_all:
123 case attr_country_id:
124 case attr_country_iso2:
125 case attr_country_iso3:
126 case attr_country_car:
127 case attr_country_name:
129 case attr_town_postal:
132 case attr_district_name:
133 case attr_town_or_district_name:
135 case attr_street_name:
137 case attr_house_number:
142 dbg(0,"unknown search '%s'\n",attr_to_name(attr_type));
148 interpolation_clear(struct interpolation *inter)
150 inter->mode=inter->side=0;
151 g_free(inter->first);
154 inter->first=inter->last=inter->curr=NULL;
158 search_fix_spaces(char *str)
162 char c,*s,*d,*ret=g_strdup(str);
164 for (i = 0 ; i < len ; i++) {
165 if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
173 if (c != ' ' || len != 0) {
177 while (c == ' ' && *s == ' ')
179 if (c == ' ' && *s == '\0') {
194 search_split_phrases(char *str)
205 if (*d == ' ' || *d == '\0') {
206 struct phrase *phrase=g_new(struct phrase, 1);
209 phrase->wordcount=++wordcount;
210 ret=g_list_append(ret, phrase);
212 } while (*d != '\0');
219 } while (*s != '\0');
220 } while (*s != '\0');
225 search_phrase_str(struct phrase *p)
227 int len=p->end-p->start;
228 char *ret=g_malloc(len+1);
229 strncpy(ret, p->start, len);
235 search_phrase_used(struct phrase *p, GList *used_phrases)
237 while (used_phrases) {
238 struct phrase *pu=used_phrases->data;
239 dbg(1,"'%s'-'%s' vs '%s'-'%s'\n",p->start,p->end,pu->start,pu->end);
240 if (p->start < pu->end && p->end > pu->start)
243 used_phrases=g_list_next(used_phrases);
249 search_by_address_compare(gconstpointer a, gconstpointer b)
251 const struct search_list_result *slra=a;
252 const struct search_list_result *slrb=b;
253 return slrb->id-slra->id;
258 search_by_address_attr(GList *results, struct search_list *sl, GList *phrases, GList *exclude, enum attr_type attr_type, int wordcount)
264 if (!search_phrase_used(tmp->data, exclude)) {
265 struct phrase *p=tmp->data;
266 int count=0,wordcount_all=wordcount+p->wordcount;
267 struct search_list_result *slr;
268 attr.u.str=search_phrase_str(p);
269 dbg(1,"%s phrase '%s'\n",attr_to_name(attr_type),attr.u.str);
270 search_list_search(sl, &attr, 0);
271 while ((slr=search_list_get_result(sl))) {
272 if (attr_type != attr_country_all) {
273 struct search_list_result *slrd=search_list_result_dup(slr);
274 slrd->id=wordcount_all;
275 results=g_list_insert_sorted(results, slrd, search_by_address_compare);
279 dbg(1,"%d results wordcount %d\n",count,wordcount_all);
281 GList *used=g_list_prepend(g_list_copy(exclude), tmp->data);
282 enum attr_type new_attr_type=attr_none;
284 case attr_country_all:
285 new_attr_type=attr_town_or_district_name;
287 case attr_town_or_district_name:
288 new_attr_type=attr_street_name;
290 case attr_street_name:
291 new_attr_type=attr_house_number;
296 if (new_attr_type != attr_none)
297 results=search_by_address_attr(results, sl, phrases, used, new_attr_type, wordcount_all);
302 tmp=g_list_next(tmp);
308 search_by_address(struct search_list *this_, char *addr)
310 char *str=search_fix_spaces(addr);
311 GList *tmp,*phrases=search_split_phrases(str);
312 struct search_list *sl=search_list_new(this_->ms);
313 this_->address_results=search_by_address_attr(NULL, sl, phrases, NULL, attr_country_all, 0);
314 this_->address_results_pos=this_->address_results;
315 search_list_destroy(sl);
319 tmp=g_list_next(tmp);
321 g_list_free(phrases);
325 search_address_results_free(struct search_list *this_)
328 tmp=this_->address_results;
330 struct search_list_result *slr=tmp->data;
332 search_list_country_destroy(slr->country);
334 search_list_town_destroy(slr->town);
336 search_list_street_destroy(slr->street);
337 if (slr->house_number)
338 search_list_house_number_destroy(slr->house_number);
342 tmp=g_list_next(tmp);
344 g_list_free(this_->address_results);
345 this_->address_results=this_->address_results_pos=NULL;
349 * @brief Start a search.
351 * @param this search_list to use for the search
352 * @param search_attr attributes to use for the search
353 * @param partial do partial search? (1=yes,0=no)
356 search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
358 struct search_list_level *le;
360 search_address_results_free(this_);
361 if (search_attr->type == attr_address) {
362 search_by_address(this_, search_attr->u.str);
363 this_->use_address_results=1;
366 this_->use_address_results=0;
367 level=search_list_level(search_attr->type);
369 interpolation_clear(&this_->inter);
370 //dbg(0,"level=%d\n", level);
374 le=&this_->levels[level];
375 search_list_search_free(this_, level);
376 le->attr=attr_dup(search_attr);
379 le=&this_->levels[level-1];
382 //dbg(0,"le=%p partial=%d\n", le, partial);
383 } else if (search_attr->type == attr_postal) {
384 g_free(this_->postal);
385 this_->postal=g_strdup(search_attr->u.str);
389 struct search_list_common *
390 search_list_select(struct search_list *this_, enum attr_type attr_type, int id, int mode)
392 int level=search_list_level(attr_type);
394 struct search_list_level *le;
395 struct search_list_common *slc;
397 le=&this_->levels[level];
401 //dbg(0,"enter level=%d %d %d %p\n", level, id, mode, curr);
404 if (! id || num == id) {
413 curr=g_list_next(curr);
415 //dbg(0,"not found\n");
420 search_list_common_new(struct item *item, struct search_list_common *common)
423 if (item_attr_get(item, attr_town_name, &attr))
424 common->town_name=map_convert_string(item->map, attr.u.str);
426 common->town_name=NULL;
427 if (item_attr_get(item, attr_county_name, &attr))
428 common->county_name=map_convert_string(item->map, attr.u.str);
430 common->county_name=NULL;
431 if (item_attr_get(item, attr_district_name, &attr))
432 common->district_name=map_convert_string(item->map, attr.u.str);
434 common->district_name=NULL;
435 if (item_attr_get(item, attr_postal, &attr))
436 common->postal=map_convert_string(item->map, attr.u.str);
437 else if (item_attr_get(item, attr_town_postal, &attr))
438 common->postal=map_convert_string(item->map, attr.u.str);
441 if (item_attr_get(item, attr_postal_mask, &attr))
442 common->postal_mask=map_convert_string(item->map, attr.u.str);
444 common->postal_mask=NULL;
448 search_list_common_dup(struct search_list_common *src, struct search_list_common *dst)
450 dst->town_name=map_convert_dup(src->town_name);
451 dst->district_name=map_convert_dup(src->district_name);
452 dst->county_name=map_convert_dup(src->county_name);
453 dst->postal=map_convert_dup(src->postal);
454 dst->postal_mask=map_convert_dup(src->postal_mask);
456 dst->c=g_new(struct pcoord, 1);
463 search_list_common_destroy(struct search_list_common *common)
465 map_convert_free(common->town_name);
466 map_convert_free(common->district_name);
467 map_convert_free(common->county_name);
468 map_convert_free(common->postal);
469 map_convert_free(common->postal_mask);
472 common->town_name=NULL;
473 common->district_name=NULL;
474 common->county_name=NULL;
476 common->postal_mask=NULL;
480 static struct search_list_country *
481 search_list_country_new(struct item *item)
483 struct search_list_country *ret=g_new0(struct search_list_country, 1);
486 ret->common.item=ret->common.unique=*item;
487 if (item_attr_get(item, attr_country_car, &attr))
488 ret->car=g_strdup(attr.u.str);
489 if (item_attr_get(item, attr_country_iso2, &attr)) {
491 ret->iso2=g_malloc(strlen(attr.u.str)+1);
492 strtolower(ret->iso2, attr.u.str);
494 ret->iso2=g_strdup(attr.u.str);
496 ret->flag=g_strdup_printf("country_%s", ret->iso2);
498 if (item_attr_get(item, attr_country_iso3, &attr))
499 ret->iso3=g_strdup(attr.u.str);
500 if (item_attr_get(item, attr_country_name, &attr))
501 ret->name=g_strdup(attr.u.str);
505 static struct search_list_country *
506 search_list_country_dup(struct search_list_country *this_)
508 struct search_list_country *ret=g_new(struct search_list_country, 1);
509 ret->car=g_strdup(this_->car);
510 ret->iso2=g_strdup(this_->iso2);
511 ret->iso3=g_strdup(this_->iso3);
512 ret->flag=g_strdup(this_->flag);
513 ret->name=g_strdup(this_->name);
518 search_list_country_destroy(struct search_list_country *this_)
528 static struct search_list_town *
529 search_list_town_new(struct item *item)
531 struct search_list_town *ret=g_new0(struct search_list_town, 1);
536 ret->common.item=ret->common.unique=*item;
537 if (item_attr_get(item, attr_town_streets_item, &attr)) {
538 dbg(1,"town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo);
539 ret->common.unique=*attr.u.item;
541 search_list_common_new(item, &ret->common);
542 if (item_attr_get(item, attr_county_name, &attr))
543 ret->county=map_convert_string(item->map,attr.u.str);
546 if (item_coord_get(item, &c, 1)) {
547 ret->common.c=g_new(struct pcoord, 1);
548 ret->common.c->x=c.x;
549 ret->common.c->y=c.y;
550 ret->common.c->pro = map_projection(item->map);
555 static struct search_list_town *
556 search_list_town_dup(struct search_list_town *this_)
558 struct search_list_town *ret=g_new0(struct search_list_town, 1);
559 ret->county=map_convert_dup(this_->county);
560 search_list_common_dup(&this_->common, &ret->common);
565 search_list_town_destroy(struct search_list_town *this_)
567 map_convert_free(this_->county);
568 search_list_common_destroy(&this_->common);
573 static struct search_list_street *
574 search_list_street_new(struct item *item)
576 struct search_list_street *ret=g_new0(struct search_list_street, 1);
580 ret->common.item=ret->common.unique=*item;
581 if (item_attr_get(item, attr_street_name, &attr))
582 ret->name=map_convert_string(item->map, attr.u.str);
585 search_list_common_new(item, &ret->common);
586 if (item_coord_get(item, &c, 1)) {
587 ret->common.c=g_new(struct pcoord, 1);
588 ret->common.c->x=c.x;
589 ret->common.c->y=c.y;
590 ret->common.c->pro = map_projection(item->map);
595 static struct search_list_street *
596 search_list_street_dup(struct search_list_street *this_)
598 struct search_list_street *ret=g_new0(struct search_list_street, 1);
599 ret->name=map_convert_dup(this_->name);
600 search_list_common_dup(&this_->common, &ret->common);
605 search_list_street_destroy(struct search_list_street *this_)
607 map_convert_free(this_->name);
608 search_list_common_destroy(&this_->common);
613 search_interpolate(struct interpolation *inter)
615 dbg(1,"interpolate %s-%s %s\n",inter->first,inter->last,inter->curr);
616 if (!inter->first || !inter->last)
619 inter->curr=g_strdup(inter->first);
621 if (strcmp(inter->curr, inter->last)) {
622 int next=atoi(inter->curr)+(inter->mode?2:1);
624 if (next == atoi(inter->last))
625 inter->curr=g_strdup(inter->last);
627 inter->curr=g_strdup_printf("%d",next);
633 dbg(1,"interpolate result %s\n",inter->curr);
638 search_interpolation_split(char *str, struct interpolation *inter)
640 char *pos=strchr(str,'-');
644 inter->first=g_strdup(str);
645 inter->last=g_strdup(str);
650 first=g_malloc(len+1);
651 strncpy(first, str, len);
653 last=g_strdup(pos+1);
654 dbg(1,"%s = %s - %s\n",str, first, last);
655 if (atoi(first) > atoi(last)) {
667 search_setup_interpolation(struct item *item, enum attr_type i0, enum attr_type i1, enum attr_type i2, struct interpolation *inter)
670 g_free(inter->first);
673 inter->first=inter->last=inter->curr=NULL;
674 dbg(1,"setup %s\n",attr_to_name(i0));
675 if (item_attr_get(item, i0, &attr)) {
676 search_interpolation_split(attr.u.str, inter);
678 } else if (item_attr_get(item, i1, &attr)) {
679 search_interpolation_split(attr.u.str, inter);
681 } else if (item_attr_get(item, i2, &attr)) {
682 search_interpolation_split(attr.u.str, inter);
690 search_match(char *str, char *search, int partial)
693 return (!g_strcasecmp(str, search));
695 return (!g_strncasecmp(str, search, strlen(search)));
698 static struct pcoord *
699 search_house_number_coordinate(struct item *item, struct interpolation *inter)
701 struct pcoord *ret=g_new(struct pcoord, 1);
702 ret->pro = map_projection(item->map);
703 dbg(1,"%s\n",item_to_name(item->type));
704 if (item->type<type_house_number_interpolation_even || item->type>type_house_number_interpolation_alphabetic) {
706 if (item_coord_get(item, &c, 1)) {
715 int hn_pos,hn_length;
716 struct coord *c=g_alloca(sizeof(struct coord)*max);
717 item_coord_rewind(item);
718 count=item_coord_get(item, c, max);
719 hn_length=atoi(inter->last)-atoi(inter->first);
721 hn_pos=atoi(inter->last)-atoi(inter->curr);
723 hn_pos=atoi(inter->curr)-atoi(inter->first);
725 int i,distance_sum=0,hn_distance;
726 int *distances=g_alloca(sizeof(int)*(count-1));
727 dbg(1,"count=%d hn_length=%d hn_pos=%d (%s of %s-%s)\n",count,hn_length,hn_pos,inter->curr,inter->first,inter->last);
733 dbg(0,"coordinate overflow\n");
734 for (i = 0 ; i < count-1 ; i++) {
735 distances[i]=navit_sqrt(transform_distance_sq(&c[i],&c[i+1]));
736 distance_sum+=distances[i];
737 dbg(1,"distance[%d]=%d\n",i,distances[i]);
739 dbg(1,"sum=%d\n",distance_sum);
740 hn_distance=distance_sum*hn_pos/hn_length;
741 dbg(1,"hn_distance=%d\n",hn_distance);
743 while (i < count-1 && hn_distance > distances[i])
744 hn_distance-=distances[i++];
745 dbg(1,"remaining distance=%d from %d\n",hn_distance,distances[i]);
746 ret->x=(c[i+1].x-c[i].x)*hn_distance/distances[i]+c[i].x;
747 ret->y=(c[i+1].y-c[i].y)*hn_distance/distances[i]+c[i].y;
755 static struct search_list_house_number *
756 search_list_house_number_new(struct item *item, struct interpolation *inter, char *inter_match, int inter_partial)
758 struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
762 ret->common.item=ret->common.unique=*item;
763 //if (item_attr_get(item, attr_street_name, &attr))
764 // dbg(0,"xx1 %s\n",attr.u.str);
765 if (item_attr_get(item, attr_house_number, &attr))
766 ret->house_number=map_convert_string(item->map, attr.u.str);
768 //if (item_attr_get(item, attr_street_name, &attr))
769 // dbg(0,"xx2 %s\n",attr.u.str);
771 //dbg(0,"interpolate 11");
772 ret->interpolation=1;
773 switch(inter->side) {
775 //dbg(0,"interpolate 11 0");
777 search_setup_interpolation(item, attr_house_number_left, attr_house_number_left_odd, attr_house_number_left_even, inter);
779 //dbg(0,"interpolate 11 -1");
780 if ((hn=search_interpolate(inter)))
783 search_setup_interpolation(item, attr_house_number_right, attr_house_number_right_odd, attr_house_number_right_even, inter);
785 //dbg(0,"interpolate 11 1");
786 if ((hn=search_interpolate(inter)))
789 //dbg(0,"interpolate 11 default");
793 if (search_match(hn, inter_match, inter_partial))
795 //dbg(0,"interpolate 22");
796 //dbg(0,"match %s %s-%s\n",hn, inter->first, inter->last);
797 ret->house_number=map_convert_string(item->map, hn);
802 //dbg(0,"interpolate 33");
803 search_list_common_new(item, &ret->common);
804 ret->common.c=search_house_number_coordinate(item, ret->interpolation?inter:NULL);
805 //dbg(0,"interpolate 44");
809 static struct search_list_house_number *
810 search_list_house_number_dup(struct search_list_house_number *this_)
812 struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
813 ret->house_number=map_convert_dup(this_->house_number);
814 search_list_common_dup(&this_->common, &ret->common);
819 search_list_house_number_destroy(struct search_list_house_number *this_)
821 map_convert_free(this_->house_number);
822 search_list_common_destroy(&this_->common);
827 search_list_result_destroy(int level, void *p)
831 search_list_country_destroy(p);
834 search_list_town_destroy(p);
837 search_list_street_destroy(p);
840 search_list_house_number_destroy(p);
845 static struct search_list_result *
846 search_list_result_dup(struct search_list_result *slr)
848 struct search_list_result *ret=g_new0(struct search_list_result, 1);
851 ret->c=g_new(struct pcoord, 1);
855 ret->country=search_list_country_dup(slr->country);
857 ret->town=search_list_town_dup(slr->town);
859 ret->street=search_list_street_dup(slr->street);
860 if (slr->house_number)
861 ret->house_number=search_list_house_number_dup(slr->house_number);
866 search_list_search_free(struct search_list *sl, int level)
868 struct search_list_level *le=&sl->levels[level];
872 mapset_search_destroy(le->search);
877 g_hash_table_destroy(le->hash);
884 search_list_result_destroy(level, curr->data);
885 next=g_list_next(curr);
889 g_list_free(le->list);
896 search_postal_merge(char *mask, char *new)
900 dbg(1,"enter %s %s\n", mask, new);
904 return g_strdup(new);
906 while (mask[i] && new[i]) {
907 if (mask[i] != '.' && mask[i] != new[i])
917 dbg(1,"merged %s with %s as %s\n", mask, new, ret);
922 search_postal_merge_replace(char *mask, char *new)
924 char *ret=search_postal_merge(mask, new);
933 postal_match(char *postal, char *mask)
936 if ((*postal != *mask) && (*mask != '.'))
950 search_add_result(struct search_list_level *le, struct search_list_common *slc)
952 struct search_list_common *slo;
954 slo=g_hash_table_lookup(le->hash, &slc->unique);
956 g_hash_table_insert(le->hash, &slc->unique, slc);
957 if (slc->postal && !slc->postal_mask) {
958 slc->postal_mask=g_strdup(slc->postal);
960 le->list=g_list_append(le->list, slc);
963 merged=search_postal_merge(slo->postal_mask, slc->postal);
965 g_free(slo->postal_mask);
966 slo->postal_mask=merged;
972 search_list_get_unique_truncate(char *common, char *result)
974 dbg(1,"%s vs %s\n",common,result);
976 if (g_utf8_get_char(common) != g_utf8_get_char(result)) {
977 dbg(1,"truncating at %s vs %s\n",common,result);
980 result=g_utf8_next_char(result);
981 common=g_utf8_next_char(common);
987 search_list_get_unique_append(char *list, char *append)
990 int llen=list?strlen(list):0;
991 int len=g_utf8_next_char(append)-append;
992 gunichar a=g_utf8_get_char(append);
994 if (g_utf8_get_char(c) == a)
996 c=g_utf8_next_char(c);
998 list=g_renew(char, list, llen+len+1);
999 strncpy(list+llen,append,len);
1000 list[llen+len]='\0';
1005 search_list_get_unique(struct search_list *this_, char *unique)
1007 int level=this_->level;
1008 struct search_list_level *le=&this_->levels[level];
1009 struct search_list_country *slc;
1010 struct search_list_town *slt;
1011 struct search_list_street *sls;
1012 struct search_list_house_number *slh;
1013 char *retf=NULL,*ret=NULL;
1014 char *strings[4]={NULL,};
1015 char *search=g_utf8_casefold(unique?unique:le->attr->u.str,-1);
1017 int search_len=strlen(search);
1018 int i,count=sizeof(strings)/sizeof(char *);
1021 dbg(0,"enter level=%d %s %s\n",level,search,unique);
1027 strings[0]=g_strdup(slc->name);
1028 strings[1]=g_strdup(slc->car);
1029 strings[2]=g_strdup(slc->iso2);
1030 strings[3]=g_strdup(slc->iso3);
1034 name=slt->common.town_name;
1035 for (i = 0 ; i < 3 ; i++)
1036 strings[i]=linguistics_expand_special(name, i);
1041 for (i = 0 ; i < 3 ; i++)
1042 strings[i]=linguistics_expand_special(name, i);
1046 name=slh->house_number;
1047 for (i = 0 ; i < 3 ; i++)
1048 strings[i]=linguistics_expand_special(name, i);
1053 dbg(1,"entry %s %s %s %s\n",strings[0],strings[1],strings[2],strings[3]);
1055 for (i = 0 ; i < count ; i++) {
1056 char *str=strings[i];
1058 char *strf=g_utf8_casefold(str,-1);
1059 dbg(1,"word %s\n",strf);
1060 if (!strncmp(strf, search, search_len)) {
1063 dbg(1,"possible next %s %s ret %s\n",strf+search_len,str+search_len,ret);
1064 ret=search_list_get_unique_append(ret, strf+search_len);
1065 ret=search_list_get_unique_append(ret, str+search_len);
1066 dbg(1,"ret now %s\n",ret);
1070 retf=g_utf8_casefold(ret,-1);
1071 dbg(1,"ret now %s\n",ret);
1073 char *end=search_list_get_unique_truncate(retf,strf);
1074 dbg(1,"%d characters\n",end-retf);
1075 if (!max || max < end)
1081 str=linguistics_next_word(str);
1087 dbg(1,"max %s (%d characters)\n",max,max-retf);
1093 dbg(1,"common %s\n",ret);
1098 dbg(0,"return %s\n",ret);
1103 * @brief Get (next) result from a search.
1105 * @param this_ search_list representing the search
1106 * @return next result
1108 struct search_list_result *
1109 search_list_get_result(struct search_list *this_)
1111 struct search_list_level *le,*leu;
1112 int level=this_->level;
1114 int has_street_name=0;
1116 if (this_->use_address_results) {
1117 struct search_list_result *ret=NULL;
1118 if (this_->address_results_pos) {
1119 ret=this_->address_results_pos->data;
1120 this_->address_results_pos=g_list_next(this_->address_results_pos);
1126 le=&this_->levels[level];
1127 //dbg(0,"le=%p\n", le);
1130 //dbg(0,"le->search=%p\n", le->search);
1133 //dbg(0,"partial=%d level=%d\n", le->partial, level);
1138 leu=&this_->levels[level-1];
1139 //dbg(0,"leu->curr=%p\n", leu->curr);
1142 //dbg(0,"*********########");
1144 struct search_list_common *slc;
1149 le->parent=leu->curr->data;
1150 leu->last=leu->curr;
1151 leu->curr=g_list_next(leu->curr);
1152 slc=(struct search_list_common *)(le->parent);
1155 if (slc->selected == leu->selected)
1161 //dbg(0,"mapset_search_new with item(%d,%d)\n", le->parent->item.id_hi, le->parent->item.id_lo);
1163 //dbg(0,"############## attr=%s\n", attr_to_name(le->attr->type));
1164 le->search=mapset_search_new(this_->ms, &le->parent->item, le->attr, le->partial);
1165 le->hash=g_hash_table_new(search_item_hash_hash, search_item_hash_equal);
1167 //dbg(0,"le->search=%p\n", le->search);
1171 this_->item=mapset_search_get_item(le->search);
1172 //dbg(0,"sssss 1 %p\n",this_->item);
1177 //dbg(0,"id_hi=%d id_lo=%d\n", this_->item->id_hi, this_->item->id_lo);
1181 if (item_attr_get(this_->item, attr_postal_mask, &postal)) {
1182 if (!postal_match(this_->postal, postal.u.str))
1184 } else if (item_attr_get(this_->item, attr_postal, &postal)) {
1185 if (strcmp(this_->postal, postal.u.str))
1189 this_->result.country=NULL;
1190 this_->result.town=NULL;
1191 this_->result.street=NULL;
1192 this_->result.c=NULL;
1193 //dbg(0,"case x LEVEL start %d\n",level);
1197 //dbg(0,"case 0 COUNTRY");
1198 p=search_list_country_new(this_->item);
1199 this_->result.country=p;
1200 this_->result.country->common.parent=NULL;
1201 this_->result.town=NULL;
1202 this_->result.street=NULL;
1203 this_->result.house_number=NULL;
1207 //dbg(0,"case 1 TOWN");
1208 p=search_list_town_new(this_->item);
1209 this_->result.town=p;
1210 this_->result.town->common.parent=this_->levels[0].last->data;
1211 this_->result.country=this_->result.town->common.parent;
1212 this_->result.c=this_->result.town->common.c;
1213 this_->result.street=NULL;
1214 this_->result.house_number=NULL;
1218 //dbg(0,"case 2 STREET");
1219 p=search_list_street_new(this_->item);
1220 this_->result.street=p;
1221 this_->result.street->common.parent=this_->levels[1].last->data;
1222 this_->result.town=this_->result.street->common.parent;
1223 this_->result.country=this_->result.town->common.parent;
1224 this_->result.c=this_->result.street->common.c;
1225 this_->result.house_number=NULL;
1229 dbg(1,"case 3 HOUSENUMBER\n");
1232 // if this housenumber has a streetname tag, set the name now
1233 if (item_attr_get(this_->item, attr_street_name, &attr2))
1235 dbg(1,"streetname: %s\n",attr2.u.str);
1239 p=search_list_house_number_new(this_->item, &this_->inter, le->attr->u.str, le->partial);
1242 interpolation_clear(&this_->inter);
1247 this_->result.house_number=p;
1248 if (!this_->result.house_number->interpolation)
1252 dbg(0,"interpolation!\n");
1255 if(le->parent && has_street_name) {
1256 struct search_list_street *street=this_->levels[level-1].last->data;
1259 s1=g_utf8_casefold(street->name,-1);
1260 s2=g_utf8_casefold(attr2.u.str,-1);
1261 cmpres=strcmp(s1,s2);
1262 dbg(1,"Compared %s with %s, got %d\n",s1,s2,cmpres);
1266 search_list_house_number_destroy(p);
1273 this_->result.house_number->common.parent=this_->levels[2].last->data;
1274 this_->result.street=this_->result.house_number->common.parent;
1275 this_->result.town=this_->result.street->common.parent;
1276 this_->result.country=this_->result.town->common.parent;
1277 this_->result.c=this_->result.house_number->common.c;
1280 if(!has_street_name) {
1281 static struct search_list_street null_street;
1282 this_->result.street=&null_street;
1288 if (search_add_result(le, p))
1291 return &this_->result;
1295 search_list_result_destroy(level, p);
1299 mapset_search_destroy(le->search);
1301 g_hash_table_destroy(le->hash);
1310 search_list_destroy(struct search_list *this_)
1312 g_free(this_->postal);