b73b42393a9d6e17ec2b2b4ff914acade748455c
[profile/ivi/navit.git] / navit / navit / search.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <string.h>
23 #include <math.h>
24 #include "debug.h"
25 #include "projection.h"
26 #include "item.h"
27 #include "map.h"
28 #include "mapset.h"
29 #include "coord.h"
30 #include "transform.h"
31 #include "search.h"
32 #include "country.h"
33
34 #if HAVE_API_ANDROID
35 #include "android.h"
36 #endif
37 #include "layout.h"
38
39 struct search_list_level {
40         struct mapset *ms;
41         struct search_list_common *parent;
42         struct attr *attr;
43         int partial;
44         int selected;
45         struct mapset_search *search;
46         GHashTable *hash;
47         GList *list,*curr,*last;
48 };
49
50 struct interpolation {
51         int side, mode, rev;
52         char *first, *last, *curr;
53 };
54
55 struct search_list {
56         struct mapset *ms;
57         struct item *item;
58         int level;
59         struct search_list_level levels[4];
60         struct search_list_result result;
61         struct search_list_result last_result;
62         int last_result_valid;
63         char *postal;
64         struct interpolation inter;
65 };
66
67 static guint
68 search_item_hash_hash(gconstpointer key)
69 {
70         const struct item *itm=key;
71         gconstpointer hashkey=(gconstpointer)GINT_TO_POINTER(itm->id_hi^itm->id_lo);
72         return g_direct_hash(hashkey);
73 }
74
75 static gboolean
76 search_item_hash_equal(gconstpointer a, gconstpointer b)
77 {
78         const struct item *itm_a=a;
79         const struct item *itm_b=b;
80         if (item_is_equal_id(*itm_a, *itm_b))
81                 return TRUE;
82         return FALSE;
83 }
84
85 struct search_list *
86 search_list_new(struct mapset *ms)
87 {
88         struct search_list *ret;
89
90         ret=g_new0(struct search_list, 1);
91         ret->ms=ms;
92
93         return ret;
94 }
95
96 static void search_list_search_free(struct search_list *sl, int level);
97
98 static int
99 search_list_level(enum attr_type attr_type)
100 {
101         switch(attr_type) {
102         case attr_country_all:
103         case attr_country_id:
104         case attr_country_iso2:
105         case attr_country_iso3:
106         case attr_country_car:
107         case attr_country_name:
108                 return 0;
109         case attr_town_postal:
110                 return 1;
111         case attr_town_name:
112         case attr_district_name:
113         case attr_town_or_district_name:
114                 return 1;
115         case attr_street_name:
116                 return 2;
117         case attr_house_number:
118                 return 3;
119         case attr_postal:
120                 return -1;
121         default:
122                 dbg(0,"unknown search '%s'\n",attr_to_name(attr_type));
123                 return -1;
124         }
125 }
126
127 static void
128 interpolation_clear(struct interpolation *inter)
129 {
130         inter->mode=inter->side=0;
131         g_free(inter->first);
132         g_free(inter->last);
133         g_free(inter->curr);
134         inter->first=inter->last=inter->curr=NULL;
135 }
136
137 void
138 search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
139 {
140         struct search_list_level *le;
141         int level=search_list_level(search_attr->type);
142         this_->item=NULL;
143         interpolation_clear(&this_->inter);
144         //dbg(0,"level=%d\n", level);
145         if (level != -1) {
146                 this_->result.id=0;
147                 this_->level=level;
148                 le=&this_->levels[level];
149                 search_list_search_free(this_, level);
150                 le->attr=attr_dup(search_attr);
151                 le->partial=partial;
152                 if (level > 0) {
153                         le=&this_->levels[level-1];
154                         le->curr=le->list;
155                 }
156                 //dbg(0,"le=%p partial=%d\n", le, partial);
157         } else if (search_attr->type == attr_postal) {
158                 g_free(this_->postal);
159                 this_->postal=g_strdup(search_attr->u.str);
160         }
161 }
162
163 struct search_list_common *
164 search_list_select(struct search_list *this_, enum attr_type attr_type, int id, int mode)
165 {
166         int level=search_list_level(attr_type);
167         int num=0;
168         struct search_list_level *le;
169         struct search_list_common *slc;
170         GList *curr;
171         le=&this_->levels[level];
172         curr=le->list;
173         if (mode > 0 || !id)
174                 le->selected=mode;
175         //dbg(0,"enter level=%d %d %d %p\n", level, id, mode, curr);
176         while (curr) {
177                 num++;
178                 if (! id || num == id) {
179                         slc=curr->data;
180                         slc->selected=mode;
181                         if (id) {
182                                 le->last=curr;
183                                 //dbg(0,"found\n");
184                                 return slc;
185                         }
186                 }
187                 curr=g_list_next(curr);
188         }
189         //dbg(0,"not found\n");
190         return NULL;
191 }
192
193 static void
194 search_list_common_new(struct item *item, struct search_list_common *common)
195 {
196         struct attr attr;
197         if (item_attr_get(item, attr_town_name, &attr))
198                 common->town_name=map_convert_string(item->map, attr.u.str);
199         else
200                 common->town_name=NULL;
201         if (item_attr_get(item, attr_county_name, &attr))
202                 common->county_name=map_convert_string(item->map, attr.u.str);
203         else
204                 common->county_name=NULL;
205         if (item_attr_get(item, attr_district_name, &attr))
206                 common->district_name=map_convert_string(item->map, attr.u.str);
207         else
208                 common->district_name=NULL;
209         if (item_attr_get(item, attr_postal, &attr))
210                 common->postal=map_convert_string(item->map, attr.u.str);
211         else if (item_attr_get(item, attr_town_postal, &attr))
212                 common->postal=map_convert_string(item->map, attr.u.str);
213         else
214                 common->postal=NULL;
215         if (item_attr_get(item, attr_postal_mask, &attr))
216                 common->postal_mask=map_convert_string(item->map, attr.u.str);
217         else
218                 common->postal_mask=NULL;
219 }
220
221 static void
222 search_list_common_destroy(struct search_list_common *common)
223 {
224         map_convert_free(common->town_name);
225         map_convert_free(common->district_name);
226         map_convert_free(common->county_name);
227         map_convert_free(common->postal);
228         map_convert_free(common->postal_mask);
229 }
230
231 static struct search_list_country *
232 search_list_country_new(struct item *item)
233 {
234         struct search_list_country *ret=g_new0(struct search_list_country, 1);
235         struct attr attr;
236
237         ret->common.item=ret->common.unique=*item;
238         if (item_attr_get(item, attr_country_car, &attr))
239                 ret->car=g_strdup(attr.u.str);
240         if (item_attr_get(item, attr_country_iso2, &attr)) {
241 #if HAVE_API_ANDROID
242                 ret->iso2=g_malloc(strlen(attr.u.str)+1);
243                 strtolower(ret->iso2, attr.u.str);
244 #else
245                 ret->iso2=g_strdup(attr.u.str);
246 #endif
247                 ret->flag=g_strdup_printf("country_%s", ret->iso2);
248         }
249         if (item_attr_get(item, attr_country_iso3, &attr))
250                 ret->iso3=g_strdup(attr.u.str);
251         if (item_attr_get(item, attr_country_name, &attr))
252                 ret->name=g_strdup(attr.u.str);
253         return ret;
254 }
255
256 static void
257 search_list_country_destroy(struct search_list_country *this_)
258 {
259         g_free(this_->car);
260         g_free(this_->iso2);
261         g_free(this_->iso3);
262         g_free(this_->flag);
263         g_free(this_->name);
264         g_free(this_);
265 }
266
267 static struct search_list_town *
268 search_list_town_new(struct item *item)
269 {
270         struct search_list_town *ret=g_new0(struct search_list_town, 1);
271         struct attr attr;
272         struct coord c;
273
274         ret->itemt=*item;
275         ret->common.item=ret->common.unique=*item;
276         if (item_attr_get(item, attr_town_streets_item, &attr)) {
277                 dbg(1,"town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo);
278                 ret->common.unique=*attr.u.item;
279         }
280         search_list_common_new(item, &ret->common);
281         if (item_attr_get(item, attr_county_name, &attr))
282                 ret->county=map_convert_string(item->map,attr.u.str);
283         else
284                 ret->county=NULL;
285         if (item_coord_get(item, &c, 1)) {
286                 ret->common.c=g_new(struct pcoord, 1);
287                 ret->common.c->x=c.x;
288                 ret->common.c->y=c.y;
289                 ret->common.c->pro = map_projection(item->map);
290         }
291         return ret;
292 }
293
294 static void
295 search_list_town_destroy(struct search_list_town *this_)
296 {
297         map_convert_free(this_->county);
298         search_list_common_destroy(&this_->common);
299         if (this_->common.c)
300                 g_free(this_->common.c);
301         g_free(this_);
302 }
303
304
305 static struct search_list_street *
306 search_list_street_new(struct item *item)
307 {
308         struct search_list_street *ret=g_new0(struct search_list_street, 1);
309         struct attr attr;
310         struct coord c;
311
312         ret->common.item=ret->common.unique=*item;
313         if (item_attr_get(item, attr_street_name, &attr))
314                 ret->name=map_convert_string(item->map, attr.u.str);
315         else
316                 ret->name=NULL;
317         search_list_common_new(item, &ret->common);
318         if (item_coord_get(item, &c, 1)) {
319                 ret->common.c=g_new(struct pcoord, 1);
320                 ret->common.c->x=c.x;
321                 ret->common.c->y=c.y;
322                 ret->common.c->pro = map_projection(item->map);
323         }
324         return ret;
325 }
326
327
328 static void
329 search_list_street_destroy(struct search_list_street *this_)
330 {
331         map_convert_free(this_->name);
332         search_list_common_destroy(&this_->common);
333         if (this_->common.c)
334         {
335                 g_free(this_->common.c);
336         }
337         g_free(this_);
338 }
339
340 static char *
341 search_interpolate(struct interpolation *inter)
342 {
343         dbg(1,"interpolate %s-%s %s\n",inter->first,inter->last,inter->curr);
344         if (!inter->first || !inter->last)
345                 return NULL;
346         if (!inter->curr)
347                 inter->curr=g_strdup(inter->first);
348         else {
349                 if (strcmp(inter->curr, inter->last)) {
350                         int next=atoi(inter->curr)+(inter->mode?2:1);
351                         g_free(inter->curr);
352                         if (next == atoi(inter->last))
353                                 inter->curr=g_strdup(inter->last);
354                         else
355                                 inter->curr=g_strdup_printf("%d",next);
356                 } else {
357                         g_free(inter->curr);
358                         inter->curr=NULL;
359                 }
360         }
361         dbg(1,"interpolate result %s\n",inter->curr);
362         return inter->curr;
363 }
364
365 static void
366 search_interpolation_split(char *str, struct interpolation *inter)
367 {
368         char *pos=strchr(str,'-');
369         char *first,*last;
370         int len;
371         if (!pos) {
372                 inter->first=g_strdup(str);
373                 inter->last=g_strdup(str);
374                 inter->rev=0;
375                 return;
376         }
377         len=pos-str;
378         first=g_malloc(len+1);
379         strncpy(first, str, len);
380         first[len]='\0';
381         last=g_strdup(pos+1);
382         dbg(1,"%s = %s - %s\n",str, first, last);
383         if (atoi(first) > atoi(last)) {
384                 inter->first=last;
385                 inter->last=first;
386                 inter->rev=1;
387         } else {
388                 inter->first=first;
389                 inter->last=last;
390                 inter->rev=0;
391         }
392 }
393
394 static int
395 search_setup_interpolation(struct item *item, enum attr_type i0, enum attr_type i1, enum attr_type i2, struct interpolation *inter)
396 {
397         struct attr attr;
398         g_free(inter->first);
399         g_free(inter->last);
400         g_free(inter->curr);
401         inter->first=inter->last=inter->curr=NULL;
402         dbg(1,"setup %s\n",attr_to_name(i0));
403         if (item_attr_get(item, i0, &attr)) {
404                 search_interpolation_split(attr.u.str, inter);
405                 inter->mode=0;
406         } else if (item_attr_get(item, i1, &attr)) {
407                 search_interpolation_split(attr.u.str, inter);
408                 inter->mode=1;
409         } else if (item_attr_get(item, i2, &attr)) {
410                 search_interpolation_split(attr.u.str, inter);
411                 inter->mode=2;
412         } else
413                 return 0;
414         return 1;
415 }
416
417 static int
418 search_match(char *str, char *search, int partial)
419 {
420         if (!partial)
421                 return (!g_strcasecmp(str, search));
422         else
423                 return (!g_strncasecmp(str, search, strlen(search)));
424 }
425
426 static struct pcoord *
427 search_house_number_coordinate(struct item *item, struct interpolation *inter)
428 {
429         struct pcoord *ret=g_new(struct pcoord, 1);
430         ret->pro = map_projection(item->map);
431         dbg(0,"%s\n",item_to_name(item->type));
432         if (item->type<type_house_number_interpolation_even || item->type>type_house_number_interpolation_alphabetic) {
433                 struct coord c;
434                 if (item_coord_get(item, &c, 1)) {
435                         ret->x=c.x;
436                         ret->y=c.y;
437                 } else {
438                         g_free(ret);
439                         ret=NULL;
440                 }
441         } else {
442                 int count,max=1024;
443                 int hn_pos,hn_length;
444                 struct coord *c=g_alloca(sizeof(struct coord)*max);
445                 item_coord_rewind(item);
446                 count=item_coord_get(item, c, max);
447                 hn_length=atoi(inter->last)-atoi(inter->first);
448                 if (inter->rev)
449                         hn_pos=atoi(inter->last)-atoi(inter->curr);
450                 else
451                         hn_pos=atoi(inter->curr)-atoi(inter->first);
452                 if (count) {
453                         int i,distance_sum=0,hn_distance;
454                         int *distances=g_alloca(sizeof(int)*(count-1));
455                         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);
456                         if (!hn_length) {
457                                 hn_length=2;
458                                 hn_pos=1;
459                         }
460                         if (count == max)
461                                 dbg(0,"coordinate overflow\n");
462                         for (i = 0 ; i < count-1 ; i++) {
463                                 distances[i]=navit_sqrt(transform_distance_sq(&c[i],&c[i+1]));
464                                 distance_sum+=distances[i];
465                                 dbg(1,"distance[%d]=%d\n",i,distances[i]);
466                         }
467                         dbg(1,"sum=%d\n",distance_sum);
468                         hn_distance=distance_sum*hn_pos/hn_length;
469                         dbg(1,"hn_distance=%d\n",hn_distance);
470                         i=0;
471                         while (i < count-1 && hn_distance > distances[i])
472                                 hn_distance-=distances[i++];
473                         dbg(1,"remaining distance=%d from %d\n",hn_distance,distances[i]);
474                         ret->x=(c[i+1].x-c[i].x)*hn_distance/distances[i]+c[i].x;
475                         ret->y=(c[i+1].y-c[i].y)*hn_distance/distances[i]+c[i].y;
476                         g_free(distances);
477                 }
478                 g_free(c);
479         }
480         return ret;
481 }
482
483 static struct search_list_house_number *
484 search_list_house_number_new(struct item *item, struct interpolation *inter, char *inter_match, int inter_partial)
485 {
486         struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
487         struct attr attr;
488         char *hn;
489
490         ret->common.item=ret->common.unique=*item;
491         //if (item_attr_get(item, attr_street_name, &attr))
492         //      dbg(0,"xx1 %s\n",attr.u.str);
493         if (item_attr_get(item, attr_house_number, &attr))
494                 ret->house_number=map_convert_string(item->map, attr.u.str);
495         else {
496                 //if (item_attr_get(item, attr_street_name, &attr))
497                 //      dbg(0,"xx2 %s\n",attr.u.str);
498                 for (;;) {
499                         //dbg(0,"interpolate 11");
500                         ret->interpolation=1;
501                         switch(inter->side) {
502                         case 0:
503                                 //dbg(0,"interpolate 11 0");
504                                 inter->side=-1;
505                                 search_setup_interpolation(item, attr_house_number_left, attr_house_number_left_odd, attr_house_number_left_even, inter);
506                         case -1:
507                                 //dbg(0,"interpolate 11 -1");
508                                 if ((hn=search_interpolate(inter)))
509                                         break;
510                                 inter->side=1;
511                                 search_setup_interpolation(item, attr_house_number_right, attr_house_number_right_odd, attr_house_number_right_even, inter);
512                         case 1:
513                                 //dbg(0,"interpolate 11 1");
514                                 if ((hn=search_interpolate(inter)))
515                                         break;
516                         default:
517                                 //dbg(0,"interpolate 11 default");
518                                 g_free(ret);
519                                 return NULL;
520                         }
521                         if (search_match(hn, inter_match, inter_partial))
522                         {
523                                 //dbg(0,"interpolate 22");
524                                 //dbg(0,"match %s %s-%s\n",hn, inter->first, inter->last);
525                                 ret->house_number=map_convert_string(item->map, hn);
526                                 break;
527                         }
528                 }
529         }
530         //dbg(0,"interpolate 33");
531         search_list_common_new(item, &ret->common);
532         ret->common.c=search_house_number_coordinate(item, ret->interpolation?inter:NULL);
533         //dbg(0,"interpolate 44");
534         return ret;
535 }
536
537 static void
538 search_list_house_number_destroy(struct search_list_house_number *this_)
539 {
540         map_convert_free(this_->house_number);
541         search_list_common_destroy(&this_->common);
542         if (this_->common.c)
543                 g_free(this_->common.c);
544         g_free(this_);
545 }
546
547 static void
548 search_list_result_destroy(int level, void *p)
549 {
550         switch (level) {
551         case 0:
552                 search_list_country_destroy(p);
553                 break;
554         case 1:
555                 search_list_town_destroy(p);
556                 break;
557         case 2:
558                 search_list_street_destroy(p);
559                 break;
560         case 3:
561                 search_list_house_number_destroy(p);
562                 break;
563         }
564 }
565
566 static void
567 search_list_search_free(struct search_list *sl, int level)
568 {
569         struct search_list_level *le=&sl->levels[level];
570         GList *next,*curr;
571         if (le->search)
572         {
573                 mapset_search_destroy(le->search);
574                 le->search=NULL;
575         }
576 #if 0 /* FIXME */
577         if (le->hash) {
578                 g_hash_table_destroy(le->hash);
579                 le->hash=NULL;
580         }
581 #endif
582         curr=le->list;
583         while (curr)
584         {
585                 search_list_result_destroy(level, curr->data);
586                 next=g_list_next(curr);
587                 curr=next;
588         }
589         attr_free(le->attr);
590         g_list_free(le->list);
591         le->list=NULL;
592         le->curr=NULL;
593         le->last=NULL;
594 }
595
596 char *
597 search_postal_merge(char *mask, char *new)
598 {
599         int i;
600         char *ret=NULL;
601         dbg(1,"enter %s %s\n", mask, new);
602         if (!new)
603                 return NULL;
604         if (!mask)
605                 return g_strdup(new);
606         i=0;
607         while (mask[i] && new[i]) {
608                 if (mask[i] != '.' && mask[i] != new[i])
609                         break;
610                 i++;
611
612         }
613         if (mask[i]) {
614                 ret=g_strdup(mask);
615                 while (mask[i])
616                         ret[i++]='.';
617         }
618         dbg(1,"merged %s with %s as %s\n", mask, new, ret);
619         return ret;
620 }
621
622 char *
623 search_postal_merge_replace(char *mask, char *new)
624 {
625         char *ret=search_postal_merge(mask, new);
626         if (!ret)
627                 return mask;
628         g_free(mask);
629         return ret;
630 }
631
632
633 static int
634 postal_match(char *postal, char *mask)
635 {
636         for (;;) {
637                 if ((*postal != *mask) && (*mask != '.'))
638                         return 0;
639                 if (!*postal) {
640                         if (!*mask)
641                                 return 1;
642                         else
643                                 return 0;
644                 }
645                 postal++;
646                 mask++;
647         }
648 }
649
650 static int
651 search_add_result(struct search_list_level *le, struct search_list_common *slc)
652 {
653         struct search_list_common *slo;
654         char *merged;
655         slo=g_hash_table_lookup(le->hash, &slc->unique);
656         if (!slo) {
657                 g_hash_table_insert(le->hash, &slc->unique, slc);
658                 if (slc->postal && !slc->postal_mask) {
659                         slc->postal_mask=g_strdup(slc->postal);
660                 }
661                 le->list=g_list_append(le->list, slc);
662                 return 1;
663         }
664         merged=search_postal_merge(slo->postal_mask, slc->postal);
665         if (merged) {
666                 g_free(slo->postal_mask);
667                 slo->postal_mask=merged;
668         }
669         return 0;
670 }
671
672 struct search_list_result *
673 search_list_get_result(struct search_list *this_)
674 {
675         struct search_list_level *le,*leu;
676         int level=this_->level;
677         struct attr attr2;
678         int has_street_name=0;
679
680         //dbg(0,"enter\n");
681         le=&this_->levels[level];
682         //dbg(0,"le=%p\n", le);
683         for (;;)
684         {
685                 //dbg(0,"le->search=%p\n", le->search);
686                 if (! le->search)
687                 {
688                         //dbg(0,"partial=%d level=%d\n", le->partial, level);
689                         if (! level)
690                                 le->parent=NULL;
691                         else
692                         {
693                                 leu=&this_->levels[level-1];
694                                 //dbg(0,"leu->curr=%p\n", leu->curr);
695                                 for (;;)
696                                 {
697                                         //dbg(0,"*********########");
698
699                                         struct search_list_common *slc;
700                                         if (! leu->curr)
701                                         {
702                                                 return NULL;
703                                         }
704                                         le->parent=leu->curr->data;
705                                         leu->last=leu->curr;
706                                         leu->curr=g_list_next(leu->curr);
707                                         slc=(struct search_list_common *)(le->parent);
708                                         if (!slc)
709                                                 break;
710                                         if (slc->selected == leu->selected)
711                                                 break;
712                                 }
713                         }
714                         if (le->parent)
715                         {
716                                 //dbg(0,"mapset_search_new with item(%d,%d)\n", le->parent->item.id_hi, le->parent->item.id_lo);
717                         }
718                         //dbg(0,"############## attr=%s\n", attr_to_name(le->attr->type));
719                         le->search=mapset_search_new(this_->ms, &le->parent->item, le->attr, le->partial);
720                         le->hash=g_hash_table_new(search_item_hash_hash, search_item_hash_equal);
721                 }
722                 //dbg(0,"le->search=%p\n", le->search);
723                 if (!this_->item)
724                 {
725                         //dbg(0,"sssss 1");
726                         this_->item=mapset_search_get_item(le->search);
727                         //dbg(0,"sssss 1 %p\n",this_->item);
728                 }
729                 if (this_->item)
730                 {
731                         void *p=NULL;
732                         //dbg(0,"id_hi=%d id_lo=%d\n", this_->item->id_hi, this_->item->id_lo);
733                         if (this_->postal)
734                         {
735                                 struct attr postal;
736                                 if (item_attr_get(this_->item, attr_postal_mask, &postal)) {
737                                         if (!postal_match(this_->postal, postal.u.str))
738                                                 continue;
739                                 } else if (item_attr_get(this_->item, attr_postal, &postal)) {
740                                         if (strcmp(this_->postal, postal.u.str))
741                                                 continue;
742                                 }
743                         }
744                         this_->result.country=NULL;
745                         this_->result.town=NULL;
746                         this_->result.street=NULL;
747                         this_->result.c=NULL;
748                         //dbg(0,"case x LEVEL start %d\n",level);
749                         switch (level)
750                         {
751                         case 0:
752                                 //dbg(0,"case 0 COUNTRY");
753                                 p=search_list_country_new(this_->item);
754                                 this_->result.country=p;
755                                 this_->result.country->common.parent=NULL;
756                                 this_->item=NULL;
757                                 break;
758                         case 1:
759                                 //dbg(0,"case 1 TOWN");
760                                 p=search_list_town_new(this_->item);
761                                 this_->result.town=p;
762                                 this_->result.town->common.parent=this_->levels[0].last->data;
763                                 this_->result.country=this_->result.town->common.parent;
764                                 this_->result.c=this_->result.town->common.c;
765                                 this_->item=NULL;
766                                 break;
767                         case 2:
768                                 //dbg(0,"case 2 STREET");
769                                 p=search_list_street_new(this_->item);
770                                 this_->result.street=p;
771                                 this_->result.street->common.parent=this_->levels[1].last->data;
772                                 this_->result.town=this_->result.street->common.parent;
773                                 this_->result.country=this_->result.town->common.parent;
774                                 this_->result.c=this_->result.street->common.c;
775                                 this_->item=NULL;
776                                 break;
777                         case 3:
778                                 dbg(1,"case 3 HOUSENUMBER\n");
779                                 has_street_name=0;
780
781                                 // if this housenumber has a streetname tag, set the name now
782                                 if (item_attr_get(this_->item, attr_street_name, &attr2))
783                                 {
784                                         dbg(1,"streetname: %s\n",attr2.u.str);
785                                         has_street_name=1;
786                                 }
787
788                                 p=search_list_house_number_new(this_->item, &this_->inter, le->attr->u.str, le->partial);
789                                 if (!p)
790                                 {
791                                         interpolation_clear(&this_->inter);
792                                         this_->item=NULL;
793                                         continue;
794                                 }
795
796                                 this_->result.house_number=p;
797                                 if (!this_->result.house_number->interpolation)
798                                 {
799                                         this_->item=NULL;
800                                 } else {
801                                         dbg(0,"interpolation!\n");
802                                 }
803
804                                 if(le->parent && has_street_name) {
805                                         struct search_list_street *street=this_->levels[level-1].last->data;
806                                         char *s1,*s2;
807                                         int cmpres;
808                                         s1=g_utf8_casefold(street->name,-1);
809                                         s2=g_utf8_casefold(attr2.u.str,-1);
810                                         cmpres=strcmp(s1,s2);
811                                         dbg(1,"Compared %s with %s, got %d\n",s1,s2,cmpres);
812                                         g_free(s1);
813                                         g_free(s2);
814                                         if(cmpres) {
815                                                 search_list_house_number_destroy(p);
816                                                 //this_->item=NULL;
817                                                 continue;
818                                         }
819                                 }
820
821
822                                 this_->result.house_number->common.parent=this_->levels[2].last->data;
823                                 this_->result.street=this_->result.house_number->common.parent;
824                                 this_->result.town=this_->result.street->common.parent;
825                                 this_->result.country=this_->result.town->common.parent;
826                                 this_->result.c=this_->result.house_number->common.c;
827
828                                 if(!has_street_name) {
829                                         static struct search_list_street null_street;
830                                         this_->result.street=&null_street;
831                                 }
832                         }
833                         if (p)
834                         {
835                                 if (search_add_result(le, p))
836                                 {
837                                         this_->result.id++;
838                                         return &this_->result;
839                                 }
840                                 else
841                                 {
842                                         search_list_result_destroy(level, p);
843                                 }
844                         }
845                 } else {
846                         mapset_search_destroy(le->search);
847                         le->search=NULL;
848                         g_hash_table_destroy(le->hash);
849                         if (! level)
850                                 break;
851                 }
852         }
853         return NULL;
854 }
855
856 void
857 search_list_destroy(struct search_list *this_)
858 {
859         g_free(this_->postal);
860         g_free(this_);
861 }
862
863 void
864 search_init(void)
865 {
866 }
867
868
869 static char *
870 search_fix_spaces(const char *str)
871 {
872         int i;
873         int len=strlen(str);
874         char c,*s,*d,*ret=g_strdup(str);
875
876         for (i = 0 ; i < len ; i++) {
877                 if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
878                         ret[i]=' ';
879         }
880         s=ret;
881         d=ret;
882         len=0;
883         do {
884                 c=*s++;
885                 if (c != ' ' || len != 0) {
886                         *d++=c;
887                         len++;
888                 }
889                 while (c == ' ' && *s == ' ')
890                         s++;
891                 if (c == ' ' && *s == '\0') {
892                         d--;
893                         len--;
894                 }
895         } while (c);
896         return ret;
897 }
898
899 static GList *
900 search_split_phrases(char *str)
901 {
902         char *tmp,*s,*d;
903         GList *ret=NULL;
904         s=str;
905         do {
906                 tmp=g_strdup(s);
907                 d=tmp+strlen(s)-1;
908                 ret=g_list_append(ret, g_strdup(s));
909                 while (d >= tmp) {
910                         if (*d == ' ') {
911                                 *d = '\0';
912                                 ret=g_list_append(ret, g_strdup(tmp));
913                         }
914                         d--;
915                 }
916                 g_free(tmp);
917                 do {
918                         s++;
919                         if (*s == ' ') {
920                                 s++;
921                                 break;
922                         }
923                 } while (*s != '\0');
924         } while (*s != '\0');
925         return ret;
926 }
927
928 static GList *
929 search_address_housenumber_real(GList *result_list, struct search_list *sl, char *street_name, GList *phrases, GList *exclude1, GList *exclude2, GList *exclude3, int partial, struct jni_object *jni)
930 {
931         // here we search actually for the housenumber
932         struct search_list_result *slr;
933         struct coord_geo g;
934         struct coord c;
935
936         dbg(1,"street:%s\n",street_name);
937         while ((slr=search_list_get_result(sl)))
938         {
939                 // does the streetname of the housenumber match the street we want?
940                 if (slr->street != NULL)
941                 if ((street_name != NULL)&&(slr->street->name != NULL))
942                 {
943                         //dbg(0,"ffffff 1.1 %s %s",street_name,slr->street->name);
944                         if (strcmp(slr->street->name, street_name)==0)
945                         {
946                                 char *buffer;
947                                 // coords of result
948                                 c.x=slr->house_number->common.c->x;
949                                 c.y=slr->house_number->common.c->y;
950                                 transform_to_geo(slr->house_number->common.c->pro, &c, &g);
951                                 //dbg(0,"g=%f %f\n",g.lat,g.lng);
952                                 //dbg(0,"###### Result with housenumber: streetname=%s\n",slr->street->name);
953                                 //dbg(0,"###### Result with housenumber: %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);
954                                 // SHN -> street with house number
955                                 // return a string like: "SHN:H111L5555:16.766:48.76:full address name is at the end"
956                                 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 max. 15 chars -> this sould be max. about 335 chars long
957                                 if (slr->town->common.postal == NULL)
958                                 {
959                                         buffer=g_strdup_printf("SHN:H%dL%d:%f:%f:%.101s, %.101s, %.101s %.15s",slr->street->common.item.id_hi,slr->street->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.town_name,slr->street->name,slr->house_number->house_number);
960                                 }
961                                 else
962                                 {
963                                         buffer=g_strdup_printf("SHN:H%dL%d:%f:%f:%.101s, %.7s %.101s, %.101s %.15s",slr->street->common.item.id_hi,slr->street->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.postal,slr->town->common.town_name,slr->street->name,slr->house_number->house_number);
964                                 }
965                                 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
966 #ifdef HAVE_API_ANDROID
967                                 // return results to android as they come in ...
968                                 android_return_search_result(jni,buffer);
969 #endif
970                                 g_free(buffer);
971                         }
972                 }
973
974         }
975         return result_list;
976 }
977
978 static GList *
979 search_address_housenumber(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, GList *exclude3, int partial, struct jni_object *jni)
980 {
981         // title is wrong
982         // this is actually "street search" and "housenumber search" is at the bottom of this function
983         //
984         // housenumbers are not found as of now (2011-02-28)
985         //
986
987         //dbg(0,"enter\n");
988         struct search_list_result *slr;
989         GList *tmp=phrases;
990         int count=0;
991         struct attr attr;
992         struct coord_geo g;
993         struct coord c;
994         struct attr attr2;
995         attr.type=attr_street_name;
996         while ((slr=search_list_get_result(sl)))
997         {
998                 char *buffer;
999                 //dbg(0,"%p %p\n",slr->country,slr->town);
1000                 //dbg(0,"%p\n",slr->street);
1001                 // dbg(0,"###### Result without housenumber: country=%s country_name=%s town=%s street=%s\n",slr->country->iso2,slr->country->name,slr->town->common.town_name,slr->street->name);
1002                 //dbg(0,"###### Result without housenumber: postal:%s\n",slr->town->common.postal);
1003                 //dbg(0,"###### Result without housenumber: postal_mask:%s\n",slr->town->common.postal_mask);
1004                 //dbg(0,"###### Result without housenumber: STR postal:%s\n",slr->street->common.postal);
1005                 //dbg(0,"###### Result without housenumber: STR postal_mask:%s\n",slr->street->common.postal_mask);
1006                 //dbg(0,"###### Result without housenumber: item id_hi:%d id_lo:%d\n",slr->street->common.item.id_hi,slr->street->common.item.id_lo);
1007
1008                 // coords of result
1009                 c.x=slr->street->common.c->x;
1010                 c.y=slr->street->common.c->y;
1011                 transform_to_geo(slr->street->common.c->pro, &c, &g);
1012                 //dbg(0,"g=%f %f\n",g.lat,g.lng);
1013
1014                 //dbg(0,"xx1");
1015                 // STR -> street
1016                 // return a string like: "STR:H1111L5555:16.766:-48.76:full address name is at the end"
1017                 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 chars -> this sould be max. about 320 chars long
1018                 if (slr->town->common.postal == NULL)
1019                 {
1020                         buffer=g_strdup_printf("STR:H%dL%d:%f:%f:%.101s,%.101s, %.101s",slr->street->common.item.id_hi,slr->street->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.town_name,slr->street->name);
1021                 }
1022                 else
1023                 {
1024                         buffer=g_strdup_printf("STR:H%dL%d:%f:%f:%.101s,%.7s %.101s, %.101s",slr->street->common.item.id_hi,slr->street->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.postal,slr->town->common.town_name,slr->street->name);
1025                 }
1026                 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1027
1028 #ifdef HAVE_API_ANDROID
1029                 // return results to android as they come in ...
1030                 android_return_search_result(jni,buffer);
1031 #endif
1032                 count++;
1033
1034                 while (tmp)
1035                 {
1036                         if (tmp != exclude1 && tmp != exclude2 && tmp != exclude3 && slr->street)
1037                         {
1038                                 attr2.type=attr_house_number;
1039                                 attr2.u.str=tmp->data;
1040                                 search_list_search(sl, &attr2, partial);
1041                                 //dbg(0,"hn str=%s\n",attr2.u.str);
1042                                 result_list=search_address_housenumber_real(result_list, sl, slr->street->name, phrases, exclude1, exclude2, exclude3, partial, jni);
1043                         }
1044                         tmp=g_list_next(tmp);
1045                 }
1046                 g_free(buffer);
1047         }
1048         if (!count)
1049         {
1050                 return result_list;
1051         }
1052         return result_list;
1053 }
1054
1055 static GList *
1056 search_address_street(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, int partial, struct jni_object *jni)
1057 {
1058         // title is wrong
1059         // this is actually "town search" !!
1060
1061         //dbg(0,"enter\n");
1062         struct search_list_result *slr;
1063         GList *tmp=phrases;
1064         int count=0;
1065         struct coord_geo g;
1066         struct coord c;
1067         struct attr attr;
1068         attr.type=attr_street_name;
1069         while ((slr=search_list_get_result(sl)))
1070         {
1071                 char *buffer;
1072                 //dbg(0,"##### sss1");
1073                 // dbg(0,"###### Result town: country=%s country_name=%s town=%s",slr->country->iso2,slr->country->name,slr->town->common.town_name);
1074                 // dbg(0,"###### Result town: postal=%s postal_mask=%s",slr->town->common.postal,slr->town->common.postal_mask);
1075
1076                 // coords of result
1077                 c.x=slr->town->common.c->x;
1078                 c.y=slr->town->common.c->y;
1079                 transform_to_geo(slr->town->common.c->pro, &c, &g);
1080
1081                 // TWN -> town
1082                 if (slr->town->common.postal == NULL)
1083                 {
1084                         buffer=g_strdup_printf("TWN:H%dL%d:%f:%f:%.101s, %.101s",slr->town->common.item.id_hi,slr->town->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.town_name);
1085                 }
1086                 else
1087                 {
1088                         buffer=g_strdup_printf("TWN:H%dL%d:%f:%f:%.101s, %.7s %.101s",slr->town->common.item.id_hi,slr->town->common.item.id_lo,g.lat,g.lng,slr->country->name,slr->town->common.postal,slr->town->common.town_name);
1089                 }
1090                 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1091 #ifdef HAVE_API_ANDROID
1092                 // return results to android as they come in ...
1093                 android_return_search_result(jni,buffer);
1094 #endif
1095
1096
1097 #if 0
1098                 dbg(0,"%s %s %s %s",slr->country->car,slr->town->name,slr->town->district,slr->street->name);
1099 #endif
1100                 /*
1101                 dbg(0,"%s %s %s\n",slr->country->iso2,slr->town->county,slr->street->name);
1102                 struct attr attr77;
1103                 if (item_attr_get(&slr->town->itemt, attr_label, &attr77))
1104                 {
1105                         dbg(0,"***search result T=%s",attr77.u.str);
1106                 }
1107                 */
1108                 count++;
1109                 g_free(buffer);
1110         }
1111         if (!count)
1112                 return result_list;
1113         //dbg(0,"count %d\n",count);
1114         while (tmp)
1115         {
1116                 if (tmp != exclude1 && tmp != exclude2)
1117                 {
1118                         attr.u.str=tmp->data;
1119                         search_list_search(sl, &attr, partial);
1120                         result_list=search_address_housenumber(result_list, sl, phrases, exclude1, exclude2, tmp, partial, jni);
1121                 }
1122                 tmp=g_list_next(tmp);
1123         }
1124         return result_list;
1125 }
1126
1127 static GList *
1128 search_address_town(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude, int partial, struct jni_object *jni)
1129 {
1130         GList *tmp=phrases;
1131         int count=0;
1132         struct attr attr;
1133         struct search_list_result *slr;
1134         //dbg(0,"enter\n");
1135         attr.type=attr_town_or_district_name;
1136         while ((slr=search_list_get_result(sl)))
1137         {
1138                 count++;
1139         }
1140         if (!count)
1141                 return result_list;
1142         //dbg(0,"count %d\n",count);
1143         while (tmp)
1144         {
1145                 if (tmp != exclude)
1146                 {
1147                         attr.u.str=tmp->data;
1148                         search_list_search(sl, &attr, partial);
1149                         result_list=search_address_street(result_list, sl, phrases, exclude, tmp, partial, jni);
1150                 }
1151                 tmp=g_list_next(tmp);
1152         }
1153         //dbg(0,"ret");
1154         return result_list;
1155 }
1156
1157 GList *
1158 search_by_address(struct search_list *sl, const char *addr, int partial, struct jni_object *jni)
1159 {
1160         char *str=search_fix_spaces(addr);
1161         GList *phrases=search_split_phrases(str);
1162         GList *ret = NULL;
1163         dbg(0,"enter %s\n",addr);
1164         ret=search_address_town(ret, sl, phrases, NULL, partial, jni);
1165
1166         g_free(str);
1167         dbg(0,"leave %p\n",ret);
1168         return ret;
1169 }
1170
1171