/[zanavi_public1]/navit/navit/search.c
ZANavi

Contents of /navit/navit/search.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (show annotations) (download)
Sun Mar 19 08:44:36 2017 UTC (7 years ago) by zoff99
File MIME type: text/plain
File size: 54307 byte(s)
updates
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
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 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <stdlib.h>
40 #include <glib.h>
41 #include <string.h>
42 #include <math.h>
43 #include "debug.h"
44 #include "projection.h"
45 #include "item.h"
46 #include "map.h"
47 #include "mapset.h"
48 #include "coord.h"
49 #include "transform.h"
50 #include "search.h"
51 #include "country.h"
52 #include "navit.h"
53
54 #if HAVE_API_ANDROID
55 #include "android.h"
56 #endif
57 #include "layout.h"
58 #include "map.h"
59 #include "linguistics.h"
60
61
62
63 // func defs
64 int search_v2_work(char *addr, char *town, char* hn, int partial, struct jni_object *jni, const char* idxfile_name);
65 void search_v2(char *addr, char *town, char* hn, int partial, struct jni_object *jni);
66 // func defs
67
68 #include "s_index.h"
69
70
71
72
73 struct search_list_level
74 {
75 struct mapset *ms;
76 struct search_list_common *parent;
77 struct attr *attr;
78 int partial;
79 int selected;
80 struct mapset_search *search;
81 GHashTable *hash;
82 GList *list, *curr, *last;
83 };
84
85 struct interpolation
86 {
87 int side, mode, rev;
88 char *first, *last, *curr;
89 };
90
91 struct search_list
92 {
93 struct mapset *ms;
94 struct item *item;
95 int level;
96 struct search_list_level levels[4];
97 struct search_list_result result;
98 struct search_list_result last_result;
99 int last_result_valid;
100 char *postal;
101 struct interpolation inter;
102 };
103
104
105 static guint search_item_hash_hash(gconstpointer key)
106 {
107 const struct item *itm = key;
108 gconstpointer hashkey = (gconstpointer) GINT_TO_POINTER(itm->id_hi ^ itm->id_lo);
109 return g_direct_hash(hashkey);
110 }
111
112 static gboolean search_item_hash_equal(gconstpointer a, gconstpointer b)
113 {
114 const struct item *itm_a = a;
115 const struct item *itm_b = b;
116 if (item_is_equal_id(*itm_a, *itm_b))
117 return TRUE;
118 return FALSE;
119 }
120
121 struct search_list *
122 search_list_new(struct mapset *ms)
123 {
124 struct search_list *ret;
125
126 ret=g_new0(struct search_list, 1);
127 ret->ms = ms;
128
129 return ret;
130 }
131
132 static void search_list_search_free(struct search_list *sl, int level);
133
134 static int search_list_level(enum attr_type attr_type)
135 {
136 switch (attr_type)
137 {
138 case attr_country_all:
139 case attr_country_id:
140 case attr_country_iso2:
141 case attr_country_iso3:
142 case attr_country_car:
143 case attr_country_name:
144 return 0;
145 case attr_town_postal:
146 return 1;
147 case attr_town_name:
148 case attr_district_name:
149 case attr_town_or_district_name:
150 return 1;
151 case attr_street_name:
152 return 2;
153 case attr_house_number:
154 return 3;
155 case attr_postal:
156 return -1;
157 default:
158 // // dbg(0, "unknown search '%s'\n", attr_to_name(attr_type));
159 return -1;
160 }
161 }
162
163 static void interpolation_clear(struct interpolation *inter)
164 {
165 inter->mode = inter->side = 0;
166 g_free(inter->first);
167 g_free(inter->last);
168 g_free(inter->curr);
169 inter->first = inter->last = inter->curr = NULL;
170 }
171
172 void search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
173 {
174 struct search_list_level *le;
175 int level = search_list_level(search_attr->type);
176 this_->item = NULL;
177 interpolation_clear(&this_->inter);
178 //// // dbg(0,"## enter\n");
179 //// dbg(0,"## level=%d\n", level);
180 if (level != -1)
181 {
182 this_->result.id = 0;
183 this_->level = level;
184 le = &this_->levels[level];
185 search_list_search_free(this_, level);
186 le->attr = attr_dup(search_attr);
187 le->partial = partial;
188 if (level > 0)
189 {
190 le = &this_->levels[level - 1];
191 le->curr = le->list;
192 }
193 //// dbg(0,"## le=%p partial=%d\n", le, partial);
194 }
195 else if (search_attr->type == attr_postal)
196 {
197 g_free(this_->postal);
198 this_->postal = g_strdup(search_attr->u.str);
199 }
200 //// dbg(0,"## return\n");
201 }
202
203 struct search_list_common *
204 search_list_select(struct search_list *this_, enum attr_type attr_type, int id, int mode)
205 {
206 int level = search_list_level(attr_type);
207 int num = 0;
208 struct search_list_level *le;
209 struct search_list_common *slc;
210 GList *curr;
211 le = &this_->levels[level];
212 curr = le->list;
213 if (mode > 0 || !id)
214 le->selected = mode;
215 //// dbg(0,"enter level=%d %d %d %p\n", level, id, mode, curr);
216 while (curr)
217 {
218 num++;
219 if (!id || num == id)
220 {
221 slc = curr->data;
222 slc->selected = mode;
223 if (id)
224 {
225 le->last = curr;
226 //// dbg(0,"found\n");
227 return slc;
228 }
229 }
230 curr = g_list_next(curr);
231 }
232 //// dbg(0,"not found\n");
233 return NULL;
234 }
235
236 static void search_list_common_new(struct item *item, struct search_list_common *common)
237 {
238 struct attr attr;
239 if (item_attr_get(item, attr_town_name, &attr))
240 common->town_name = map_convert_string(item->map, attr.u.str);
241 else
242 common->town_name = NULL;
243 if (item_attr_get(item, attr_county_name, &attr))
244 common->county_name = map_convert_string(item->map, attr.u.str);
245 else
246 common->county_name = NULL;
247 if (item_attr_get(item, attr_district_name, &attr))
248 common->district_name = map_convert_string(item->map, attr.u.str);
249 else
250 common->district_name = NULL;
251 if (item_attr_get(item, attr_postal, &attr))
252 common->postal = map_convert_string(item->map, attr.u.str);
253 else if (item_attr_get(item, attr_town_postal, &attr))
254 common->postal = map_convert_string(item->map, attr.u.str);
255 else
256 common->postal = NULL;
257 if (item_attr_get(item, attr_postal_mask, &attr))
258 common->postal_mask = map_convert_string(item->map, attr.u.str);
259 else
260 common->postal_mask = NULL;
261 }
262
263 static void search_list_common_destroy(struct search_list_common *common)
264 {
265 map_convert_free(common->town_name);
266 map_convert_free(common->district_name);
267 map_convert_free(common->county_name);
268 map_convert_free(common->postal);
269 map_convert_free(common->postal_mask);
270 }
271
272 static struct search_list_country *
273 search_list_country_new(struct item *item)
274 {
275 struct search_list_country *ret=g_new0(struct search_list_country, 1);
276 struct attr attr;
277
278 ret->common.item = ret->common.unique = *item;
279 if (item_attr_get(item, attr_country_car, &attr))
280 ret->car = g_strdup(attr.u.str);
281 if (item_attr_get(item, attr_country_iso2, &attr))
282 {
283 #if HAVE_API_ANDROID
284 ret->iso2=g_malloc(strlen(attr.u.str)+1);
285 strtolower(ret->iso2, attr.u.str);
286 #else
287 ret->iso2 = g_strdup(attr.u.str);
288 #endif
289 ret->flag = g_strdup_printf("country_%s", ret->iso2);
290 }
291 if (item_attr_get(item, attr_country_iso3, &attr))
292 ret->iso3 = g_strdup(attr.u.str);
293 if (item_attr_get(item, attr_country_name, &attr))
294 ret->name = g_strdup(attr.u.str);
295 return ret;
296 }
297
298 static void search_list_country_destroy(struct search_list_country *this_)
299 {
300 g_free(this_->car);
301 g_free(this_->iso2);
302 g_free(this_->iso3);
303 g_free(this_->flag);
304 g_free(this_->name);
305 g_free(this_);
306 }
307
308 static struct search_list_town *
309 search_list_town_new(struct item *item)
310 {
311 struct search_list_town *ret=g_new0(struct search_list_town, 1);
312 struct attr attr;
313 struct coord c;
314
315 ret->itemt = *item;
316 ret->common.item = ret->common.unique = *item;
317
318 if (item_attr_get(item, attr_town_streets_item, &attr))
319 {
320 //// dbg(1, "town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo);
321 ret->common.unique = *attr.u.item;
322 }
323
324 search_list_common_new(item, &ret->common);
325
326 if (item_attr_get(item, attr_county_name, &attr))
327 {
328 ret->county = map_convert_string(item->map, attr.u.str);
329 }
330 else
331 {
332 ret->county = NULL;
333 }
334
335 if (item_coord_get(item, &c, 1))
336 {
337 ret->common.c=g_new(struct pcoord, 1);
338 ret->common.c->x = c.x;
339 ret->common.c->y = c.y;
340 ret->common.c->pro = map_projection(item->map);
341 }
342 else
343 {
344 // some error with lat/lng !!
345 // but still return something, or app will crash
346 ret->common.c=g_new(struct pcoord, 1);
347 ret->common.c->x = 0;
348 ret->common.c->y = 0;
349 ret->common.c->pro = map_projection(item->map);
350 }
351 return ret;
352 }
353
354 static void search_list_town_destroy(struct search_list_town *this_)
355 {
356 map_convert_free(this_->county);
357 search_list_common_destroy(&this_->common);
358 if (this_->common.c)
359 g_free(this_->common.c);
360 g_free(this_);
361 }
362
363 static struct search_list_street *
364 search_list_street_new(struct item *item)
365 {
366 struct search_list_street *ret=g_new0(struct search_list_street, 1);
367 struct attr attr;
368 struct coord c;
369
370 ret->common.item = ret->common.unique = *item;
371 if (item_attr_get(item, attr_street_name, &attr))
372 {
373 ret->name = map_convert_string(item->map, attr.u.str);
374 }
375 else
376 {
377 ret->name = NULL;
378 }
379 search_list_common_new(item, &ret->common);
380 if (item_coord_get(item, &c, 1))
381 {
382 ret->common.c=g_new(struct pcoord, 1);
383 ret->common.c->x = c.x;
384 ret->common.c->y = c.y;
385 ret->common.c->pro = map_projection(item->map);
386 }
387 else
388 {
389 // some error with lat/lng !!
390 // but still return something, or app will crash
391 ret->common.c=g_new(struct pcoord, 1);
392 ret->common.c->x = 0;
393 ret->common.c->y = 0;
394 ret->common.c->pro = map_projection(item->map);
395 }
396 return ret;
397 }
398
399 static void search_list_street_destroy(struct search_list_street *this_)
400 {
401 map_convert_free(this_->name);
402 search_list_common_destroy(&this_->common);
403 if (this_->common.c)
404 {
405 g_free(this_->common.c);
406 }
407 g_free(this_);
408 }
409
410 static char *
411 search_interpolate(struct interpolation *inter)
412 {
413 // dbg(1, "interpolate %s-%s %s\n", inter->first, inter->last, inter->curr);
414 if (!inter->first || !inter->last)
415 return NULL;
416 if (!inter->curr)
417 inter->curr = g_strdup(inter->first);
418 else
419 {
420 if (strcmp(inter->curr, inter->last))
421 {
422 int next = atoi(inter->curr) + (inter->mode ? 2 : 1);
423 g_free(inter->curr);
424 if (next == atoi(inter->last))
425 inter->curr = g_strdup(inter->last);
426 else
427 inter->curr = g_strdup_printf("%d", next);
428 }
429 else
430 {
431 g_free(inter->curr);
432 inter->curr = NULL;
433 }
434 }
435 // dbg(1, "interpolate result %s\n", inter->curr);
436 return inter->curr;
437 }
438
439 static void search_interpolation_split(char *str, struct interpolation *inter)
440 {
441 char *pos = strchr(str, '-');
442 char *first, *last;
443 int len;
444 if (!pos)
445 {
446 inter->first = g_strdup(str);
447 inter->last = g_strdup(str);
448 inter->rev = 0;
449 return;
450 }
451 len = pos - str;
452 first = g_malloc(len + 1);
453 strncpy(first, str, len);
454 first[len] = '\0';
455 last = g_strdup(pos + 1);
456 // dbg(1, "%s = %s - %s\n", str, first, last);
457 if (atoi(first) > atoi(last))
458 {
459 inter->first = last;
460 inter->last = first;
461 inter->rev = 1;
462 }
463 else
464 {
465 inter->first = first;
466 inter->last = last;
467 inter->rev = 0;
468 }
469 }
470
471 static int search_setup_interpolation(struct item *item, enum attr_type i0, enum attr_type i1, enum attr_type i2, struct interpolation *inter)
472 {
473 struct attr attr;
474 g_free(inter->first);
475 g_free(inter->last);
476 g_free(inter->curr);
477 inter->first = inter->last = inter->curr = NULL;
478 // dbg(1, "setup %s\n", attr_to_name(i0));
479 if (item_attr_get(item, i0, &attr))
480 {
481 search_interpolation_split(attr.u.str, inter);
482 inter->mode = 0;
483 }
484 else if (item_attr_get(item, i1, &attr))
485 {
486 search_interpolation_split(attr.u.str, inter);
487 inter->mode = 1;
488 }
489 else if (item_attr_get(item, i2, &attr))
490 {
491 search_interpolation_split(attr.u.str, inter);
492 inter->mode = 2;
493 }
494 else
495 return 0;
496 return 1;
497 }
498
499 static int search_match(char *str, char *search, int partial)
500 {
501 if (!partial)
502 return (!g_strcasecmp(str, search));
503 else
504 return (!g_strncasecmp(str, search, strlen(search)));
505 }
506
507 static struct pcoord *
508 search_house_number_coordinate(struct item *item, struct interpolation *inter)
509 {
510 struct pcoord *ret=g_new(struct pcoord, 1);
511 ret->pro = map_projection(item->map);
512
513 // // dbg(0,"001t: %s\n", item_to_name(item->type));
514
515 if (item_is_point(*item))
516 {
517 struct coord c;
518 if (item_coord_get(item, &c, 1))
519 {
520 ret->x = c.x;
521 ret->y = c.y;
522 }
523 else
524 {
525 g_free(ret);
526 ret = NULL;
527 }
528 }
529 else
530 {
531 int count, max = 1024;
532 int hn_pos, hn_length;
533 struct coord *c = g_alloca(sizeof(struct coord) * max);
534 item_coord_rewind(item);
535 count = item_coord_get(item, c, max);
536 hn_length = atoi(inter->last) - atoi(inter->first);
537 if (inter->rev)
538 hn_pos = atoi(inter->last) - atoi(inter->curr);
539 else
540 hn_pos = atoi(inter->curr) - atoi(inter->first);
541
542 if (count)
543 {
544 int i, distance_sum = 0, hn_distance;
545 int *distances = g_alloca(sizeof(int) * (count - 1));
546 // 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);
547 if (!hn_length)
548 {
549 hn_length = 2;
550 hn_pos = 1;
551 }
552 if (count == max)
553 // dbg(0, "coordinate overflow\n");
554 for (i = 0; i < count - 1; i++)
555 {
556 distances[i] = navit_sqrt(transform_distance_sq(&c[i], &c[i + 1]));
557 distance_sum += distances[i];
558 // dbg(1, "distance[%d]=%d\n", i, distances[i]);
559 }
560 // dbg(1, "sum=%d\n", distance_sum);
561 hn_distance = distance_sum * hn_pos / hn_length;
562 // dbg(1, "hn_distance=%d\n", hn_distance);
563 i = 0;
564 while (i < count - 1 && hn_distance > distances[i])
565 hn_distance -= distances[i++];
566 // dbg(1, "remaining distance=%d from %d\n", hn_distance, distances[i]);
567 ret->x = (c[i + 1].x - c[i].x) * hn_distance / distances[i] + c[i].x;
568 ret->y = (c[i + 1].y - c[i].y) * hn_distance / distances[i] + c[i].y;
569 }
570 }
571 return ret;
572 }
573
574 static struct search_list_house_number *
575 search_list_house_number_new(struct item *item, struct interpolation *inter, char *inter_match, int inter_partial)
576 {
577 struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
578 struct attr attr;
579 char *hn;
580
581 //// dbg(0,"@@@@ enter @@@@\n");
582
583 ret->common.item = ret->common.unique = *item;
584 //if (item_attr_get(item, attr_street_name, &attr))
585 // // dbg(0,"xx1 %s\n",attr.u.str);
586 if (item_attr_get(item, attr_house_number, &attr))
587 {
588 ret->house_number = map_convert_string(item->map, attr.u.str);
589 }
590 else
591 {
592 //if (item_attr_get(item, attr_street_name, &attr))
593 // // dbg(0,"xx2 %s\n",attr.u.str);
594 for (;;)
595 {
596 //// dbg(0,"interpolate 11");
597 ret->interpolation = 1;
598 switch (inter->side)
599 {
600 case 0:
601 //// dbg(0,"interpolate 11 0");
602 inter->side = -1;
603 search_setup_interpolation(item, attr_house_number_left, attr_house_number_left_odd, attr_house_number_left_even, inter);
604 case -1:
605 //// dbg(0,"interpolate 11 -1");
606 if ((hn = search_interpolate(inter)))
607 break;
608 inter->side = 1;
609 search_setup_interpolation(item, attr_house_number_right, attr_house_number_right_odd, attr_house_number_right_even, inter);
610 case 1:
611 //// dbg(0,"interpolate 11 1");
612 if ((hn = search_interpolate(inter)))
613 break;
614 default:
615 //// dbg(0,"interpolate 11 default");
616 g_free(ret);
617 return NULL;
618 }
619 if (search_match(hn, inter_match, inter_partial))
620 {
621 //// dbg(0,"interpolate 22");
622 //// dbg(0,"match %s %s-%s\n",hn, inter->first, inter->last);
623 ret->house_number = map_convert_string(item->map, hn);
624 break;
625 }
626 }
627 }
628 search_list_common_new(item, &ret->common);
629 ret->common.c = search_house_number_coordinate(item, ret->interpolation ? inter : NULL);
630 return ret;
631 }
632
633 static void search_list_house_number_destroy(struct search_list_house_number *this_)
634 {
635 map_convert_free(this_->house_number);
636 search_list_common_destroy(&this_->common);
637 if (this_->common.c)
638 g_free(this_->common.c);
639 g_free(this_);
640 }
641
642 static void search_list_result_destroy(int level, void *p)
643 {
644 switch (level)
645 {
646 case 0:
647 search_list_country_destroy(p);
648 break;
649 case 1:
650 search_list_town_destroy(p);
651 break;
652 case 2:
653 search_list_street_destroy(p);
654 break;
655 case 3:
656 search_list_house_number_destroy(p);
657 break;
658 }
659 }
660
661 static void search_list_search_free(struct search_list *sl, int level)
662 {
663 //// dbg(0,"enter\n");
664
665 struct search_list_level *le = &sl->levels[level];
666 GList *next, *curr;
667 if (le->search)
668 {
669 mapset_search_destroy(le->search);
670 le->search = NULL;
671 }
672 #if 0 /* FIXME */
673 if (le->hash)
674 {
675 g_hash_table_destroy(le->hash);
676 le->hash=NULL;
677 }
678 #endif
679 curr = le->list;
680 while (curr)
681 {
682 search_list_result_destroy(level, curr->data);
683 next = g_list_next(curr);
684 curr = next;
685 }
686 attr_free(le->attr);
687 g_list_free(le->list);
688 le->list = NULL;
689 le->curr = NULL;
690 le->last = NULL;
691
692 //// dbg(0,"return\n");
693 }
694
695 char *
696 search_postal_merge(char *mask, char *new)
697 {
698 int i;
699 char *ret = NULL;
700 // dbg(1, "enter %s %s\n", mask, new);
701 if (!new)
702 return NULL;
703 if (!mask)
704 return g_strdup(new);
705 i = 0;
706 while (mask[i] && new[i])
707 {
708 if (mask[i] != '.' && mask[i] != new[i])
709 break;
710 i++;
711
712 }
713 if (mask[i])
714 {
715 ret = g_strdup(mask);
716 while (mask[i])
717 ret[i++] = '.';
718 }
719 // dbg(1, "merged %s with %s as %s\n", mask, new, ret);
720 return ret;
721 }
722
723 char *
724 search_postal_merge_replace(char *mask, char *new)
725 {
726 char *ret = search_postal_merge(mask, new);
727 if (!ret)
728 return mask;
729 g_free(mask);
730 return ret;
731 }
732
733 static int postal_match(char *postal, char *mask)
734 {
735 for (;;)
736 {
737 if ((*postal != *mask) && (*mask != '.'))
738 return 0;
739 if (!*postal)
740 {
741 if (!*mask)
742 return 1;
743 else
744 return 0;
745 }
746 postal++;
747 mask++;
748 }
749 }
750
751 static int search_add_result(struct search_list_level *le, struct search_list_common *slc)
752 {
753 struct search_list_common *slo;
754 char *merged;
755
756 //// dbg(0,"enter\n");
757
758 //slo=g_hash_table_lookup(le->hash, &slc->unique);
759 //if (!slo) {
760 //g_hash_table_insert(le->hash, &slc->unique, slc);
761 if (slc->postal && !slc->postal_mask)
762 {
763 slc->postal_mask = g_strdup(slc->postal);
764 }
765 // ******
766 g_list_free(le->list);
767 le->list = NULL;
768 // ******
769 le->list = g_list_append(le->list, slc);
770 return 1;
771 //}
772 merged = search_postal_merge(slo->postal_mask, slc->postal);
773 if (merged)
774 {
775 g_free(slo->postal_mask);
776 slo->postal_mask = merged;
777 }
778 return 0;
779 }
780
781 struct search_list_result *
782 search_list_get_result(struct search_list *this_)
783 {
784 struct search_list_level *le, *leu;
785 int level = this_->level;
786 struct attr attr2;
787 int has_street_name = 0;
788
789 //// dbg(0,"******* enter *******\n");
790 le = &this_->levels[level];
791 //// dbg(0,"le=%p\n", le);
792 for (;;)
793 {
794 //// dbg(0,"le->search=%p\n", le->search);
795 if (!le->search)
796 {
797 //// dbg(0,"partial=%d level=%d\n", le->partial, level);
798 if (!level)
799 le->parent = NULL;
800 else
801 {
802 leu = &this_->levels[level - 1];
803 //// dbg(0,"leu->curr=%p\n", leu->curr);
804 for (;;)
805 {
806 //// dbg(0,"*********########");
807
808 struct search_list_common *slc;
809 if (!leu->curr)
810 {
811 return NULL;
812 }
813 le->parent = leu->curr->data;
814 leu->last = leu->curr;
815 leu->curr = g_list_next(leu->curr);
816 slc = (struct search_list_common *) (le->parent);
817 if (!slc)
818 break;
819 if (slc->selected == leu->selected)
820 break;
821 }
822 }
823 #if 0
824 if (le->parent)
825 {
826 // dbg(0,"mapset_search_new with item(%d,%d)\n", le->parent->item.id_hi, le->parent->item.id_lo);
827 }
828 else
829 {
830 // dbg(0,"NO parent!!\n");
831 }
832 // dbg(0,"############## attr=%s\n", attr_to_name(le->attr->type));
833 #endif
834 le->search = mapset_search_new(this_->ms, &le->parent->item, le->attr, le->partial);
835 // ** DOC ** mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial)
836 le->hash = g_hash_table_new(search_item_hash_hash, search_item_hash_equal);
837 }
838
839 //// dbg(0,"le->search=%p\n", le->search);
840
841 if (!this_->item)
842 {
843 //// dbg(0,"sssss 1");
844 this_->item = mapset_search_get_item(le->search);
845 //// dbg(0,"sssss 1 %p\n",this_->item);
846 }
847
848 if (this_->item)
849 {
850 void *p = NULL;
851 //// dbg(0,"id_hi=%d id_lo=%d\n", this_->item->id_hi, this_->item->id_lo);
852 if (this_->postal)
853 {
854 struct attr postal;
855 if (item_attr_get(this_->item, attr_postal_mask, &postal))
856 {
857 if (!postal_match(this_->postal, postal.u.str))
858 continue;
859 }
860 else if (item_attr_get(this_->item, attr_postal, &postal))
861 {
862 if (strcmp(this_->postal, postal.u.str))
863 continue;
864 }
865 }
866 this_->result.country = NULL;
867 this_->result.town = NULL;
868 this_->result.street = NULL;
869 this_->result.c = NULL;
870 //// dbg(0,"case x LEVEL start %d\n",level);
871 switch (level)
872 {
873 case 0:
874 //// dbg(0,"case 0 COUNTRY");
875 p = search_list_country_new(this_->item);
876 this_->result.country = p;
877 this_->result.country->common.parent = NULL;
878 this_->item = NULL;
879 break;
880 case 1:
881 //// dbg(0,"case 1 TOWN");
882 p = search_list_town_new(this_->item);
883 this_->result.town = p;
884 this_->result.town->common.parent = this_->levels[0].last->data;
885 this_->result.country = this_->result.town->common.parent;
886 this_->result.c = this_->result.town->common.c;
887 this_->item = NULL;
888 break;
889 case 2:
890 //// dbg(0,"case 2 STREET");
891 p = search_list_street_new(this_->item);
892 this_->result.street = p;
893 this_->result.street->common.parent = this_->levels[1].last->data;
894 this_->result.town = this_->result.street->common.parent;
895 this_->result.country = this_->result.town->common.parent;
896 this_->result.c = this_->result.street->common.c;
897 this_->item = NULL;
898 break;
899 case 3:
900 //// dbg(0,"case 3 HOUSENUMBER");
901 has_street_name = 0;
902
903 // if this housenumber has a streetname tag, set the name now
904 if (item_attr_get(this_->item, attr_street_name, &attr2))
905 {
906 // // dbg(0,"streetname: %s\n",attr2.u.str);
907 has_street_name = 1;
908 }
909
910 //// dbg(0,"case 3 XXXX 1\n");
911 p = search_list_house_number_new(this_->item, &this_->inter, le->attr->u.str, le->partial);
912 //// dbg(0,"case 3 XXXX 2\n");
913 if (!p)
914 {
915 interpolation_clear(&this_->inter);
916 this_->item = NULL;
917 continue;
918 }
919 //// dbg(0,"case 3 XXXX 3\n");
920 this_->result.house_number = p;
921 if (!this_->result.house_number->interpolation)
922 {
923 this_->item = NULL;
924 }
925
926 this_->result.house_number->common.parent = this_->levels[2].last->data;
927 this_->result.street = this_->result.house_number->common.parent;
928 this_->result.town = this_->result.street->common.parent;
929 this_->result.country = this_->result.town->common.parent;
930 this_->result.c = this_->result.house_number->common.c;
931
932 //// dbg(0,"case 3 XXXX 4\n");
933 if (has_street_name == 1)
934 {
935 gchar *tmp_name = g_strdup(attr2.u.str);
936 this_->result.street->name = tmp_name;
937 //// dbg(0,"res streetname=%s\n",this_->result.street->name);
938 }
939 else
940 {
941 //
942 // this crashes all the time -> so dont use!
943 //static struct search_list_street null_street;
944 //this_->result.street=&null_street;
945 // this crashes all the time -> so dont use!
946 //
947 this_->result.street->name = NULL;
948 }
949 //// dbg(0,"case 3 XXXX 5\n");
950 break;
951 }
952 // CASE END *********
953
954 //// dbg(0,"case end\n");
955
956 if (p)
957 {
958 if (search_add_result(le, p))
959 {
960 //** this_->result.id++;
961 this_->result.id = 0;
962 //// dbg(0,"++++ return result\n");
963 return &this_->result;
964 }
965 else
966 {
967 search_list_result_destroy(level, p);
968 // return &this_->result;
969 }
970 }
971 }
972 else
973 {
974 mapset_search_destroy(le->search);
975 le->search = NULL;
976 g_hash_table_destroy(le->hash);
977 if (!level)
978 {
979 break;
980 }
981 }
982 }
983 return NULL;
984 }
985
986 void search_list_destroy(struct search_list *this_)
987 {
988 g_free(this_->postal);
989 g_free(this_);
990 }
991
992 void search_init(void)
993 {
994 }
995
996 static char *
997 search_fix_spaces(char *str)
998 {
999 int i;
1000 int len = strlen(str);
1001 char c, *s, *d, *ret = g_strdup(str);
1002
1003 for (i = 0; i < len; i++)
1004 {
1005 if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
1006 ret[i] = ' ';
1007 }
1008 s = ret;
1009 d = ret;
1010 len = 0;
1011 do
1012 {
1013 c = *s++;
1014 if (c != ' ' || len != 0)
1015 {
1016 *d++ = c;
1017 len++;
1018 }
1019 while (c == ' ' && *s == ' ')
1020 s++;
1021 if (c == ' ' && *s == '\0')
1022 {
1023 d--;
1024 len--;
1025 }
1026 }
1027 while (c);
1028 return ret;
1029 }
1030
1031 static GList *
1032 search_split_phrases(char *str)
1033 {
1034 char *tmp, *s, *d;
1035 GList *ret = NULL;
1036 s = str;
1037 do
1038 {
1039 tmp = g_strdup(s);
1040 d = tmp + strlen(s) - 1;
1041 ret = g_list_append(ret, g_strdup(s));
1042 while (d >= tmp)
1043 {
1044 if (*d == ' ')
1045 {
1046 *d = '\0';
1047 ret = g_list_append(ret, g_strdup(tmp));
1048 }
1049 d--;
1050 }
1051 g_free(tmp);
1052 do
1053 {
1054 s++;
1055 if (*s == ' ')
1056 {
1057 s++;
1058 break;
1059 }
1060 }
1061 while (*s != '\0');
1062 }
1063 while (*s != '\0');
1064 return ret;
1065 }
1066
1067
1068
1069 static int search_address_housenumber_for_street(char *hn_name_match, char *street_name_match, char *town_string, struct coord *c, int partial, struct jni_object *jni)
1070 {
1071 struct item *item;
1072 struct map_rect *mr = NULL;
1073 struct mapset *ms;
1074 struct mapset_handle *msh;
1075 struct map* map = NULL;
1076 struct attr map_name_attr;
1077 struct attr attr;
1078 struct pcoord center99;
1079 struct map_selection *sel;
1080 int search_radius_this;
1081 int search_order;
1082 struct attr att;
1083 struct attr att2;
1084 struct attr debug_att2;
1085 char *town_string2 = NULL;
1086 char *hn_fold = NULL;
1087 char *street_name_fold = NULL;
1088 int search_results_found_ = 0;
1089 int max_townname_plus_1 = MAX_INDEXSEARCH_TOWNNAME + 1;
1090
1091 ms = global_navit->mapsets->data;
1092 msh = mapset_open(ms);
1093
1094 search_order = 18;
1095 search_radius_this = global_search_radius_for_housenumbers; // old value: 20; // search this far around street-coord to find potential housenumbers for this street
1096
1097 hn_fold = linguistics_fold_and_prepare_complete(hn_name_match, 0);
1098 street_name_fold = linguistics_fold_and_prepare_complete(street_name_match, 0);
1099
1100 if (!street_name_fold)
1101 {
1102 return NULL;
1103 }
1104
1105 if (!hn_fold)
1106 {
1107 return NULL;
1108 }
1109
1110 if (strlen(street_name_fold) < 1)
1111 {
1112 if (hn_fold)
1113 {
1114 g_free(hn_fold);
1115 }
1116
1117 if (street_name_fold)
1118 {
1119 g_free(street_name_fold);
1120 }
1121 return NULL;
1122 }
1123
1124 if (strlen(hn_fold) < 1)
1125 {
1126 if (hn_fold)
1127 {
1128 g_free(hn_fold);
1129 }
1130
1131 if (street_name_fold)
1132 {
1133 g_free(street_name_fold);
1134 }
1135 return NULL;
1136 }
1137
1138 //dbg(0, "SEARCH:HM:010a:townstr=%p", town_string);
1139 if (town_string)
1140 {
1141 //dbg(0, "SEARCH:HM:010b:townstr=%s", town_string);
1142
1143 if (strlen(town_string) > MAX_INDEXSEARCH_TOWNNAME)
1144 {
1145 town_string2 = town_string;
1146 town_string2[max_townname_plus_1] = '\0';
1147 town_string2 = linguistics_check_utf8_string(town_string2);
1148 }
1149 else
1150 {
1151 town_string2 = town_string;
1152 }
1153 }
1154
1155 center99.x = c->x;
1156 center99.y = c->y;
1157 sel = map_selection_rect_new(&center99, search_radius_this, search_order);
1158 sel->range.min = type_house_number;
1159 sel->range.max = type_house_number;
1160 //sel->u.c_rect.lu.x = center99.x - search_radius_this;
1161 //sel->u.c_rect.lu.y = center99.y + search_radius_this;
1162 //sel->u.c_rect.rl.x = center99.x + search_radius_this;
1163 //sel->u.c_rect.rl.y = center99.y - search_radius_this;
1164
1165
1166 // dbg(0, "hn=%s hn fold=%s sn=%s partial=%d street_name_fold=%s\n", hn_name_match, hn_fold, street_name_match, partial, street_name_fold);
1167 // dbg(0, "cx=%d cy=%d\n", c->x, c->y);
1168
1169 while (msh && (map = mapset_next(msh, 0)))
1170 {
1171 if (offline_search_break_searching == 1)
1172 {
1173 break;
1174 }
1175
1176 if (map_get_attr(map, attr_name, &map_name_attr, NULL))
1177 {
1178 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
1179 {
1180 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/navitmap", map_name_attr.u.str, 43) == 0)
1181 {
1182 // its an sdcard map
1183 mr = map_rect_new(map, sel);
1184 if (mr)
1185 {
1186 while ((item = map_rect_get_item(mr)))
1187 {
1188 if (offline_search_break_searching == 1)
1189 {
1190 break;
1191 }
1192
1193 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1194 g_mem_profile();
1195 #endif
1196
1197 if (item->type == type_house_number)
1198 {
1199 // does it have a housenumber?
1200 if (item_attr_get(item, attr_house_number, &att))
1201 {
1202
1203
1204 // -- DEBUG -- //if (!strncmp(att.u.str, "11", 2))
1205 //{
1206
1207 //dbg(0, "----------\n");
1208 //dbg(0, "XY:hn1 attr=%s fold=%s item->type=%d\n", att.u.str, hn_fold, item->type);
1209 //if (item_attr_get(item, attr_street_name, &debug_att2))
1210 //{
1211 // dbg(0, "XY:hn1 str attr=%s str fold=%s\n", debug_att2.u.str, street_name_fold);
1212 //}
1213 //item_attr_rewind(item);
1214
1215 // match housenumber to our string
1216 if (!ascii_cmp_local_faster(att.u.str, hn_fold, partial))
1217 {
1218 //dbg(0, "XY:found hn match!\n");
1219
1220 // if this housenumber has a streetname tag, compare it now
1221 if (item_attr_get(item, attr_street_name, &att2))
1222 {
1223 //dbg(0, "XY:XX:hn str attr=%s hn=%s\n", att2.u.str, att.u.str);
1224
1225 if (!ascii_cmp_local_faster(att2.u.str, street_name_fold, partial))
1226 {
1227 // coords of result
1228 struct coord c2;
1229 char *buffer;
1230
1231 if (item_coord_get(item, &c2, 1))
1232 {
1233 // SHN -> street with house number
1234 // return a string like: "SHN:H111L5555:16.766:48.76:full address name is at the end"
1235 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 max. 15 chars -> this sould be max. about 335 chars long
1236 if (town_string2)
1237 {
1238 buffer = g_strdup_printf("SHN:H0L0:%d:%d:%s %s, %.*s", c2.y, c2.x, att2.u.str, att.u.str, max_townname_plus_1, town_string2);
1239 }
1240 else
1241 {
1242 buffer = g_strdup_printf("SHN:H0L0:%d:%d:%s %s", c2.y, c2.x, att2.u.str, att.u.str);
1243 }
1244 //dbg(0,"buffer HN=%s\n", buffer);
1245
1246 #ifdef HAVE_API_ANDROID
1247 // return results to android as they come in ...
1248 android_return_search_result(jni,buffer);
1249 search_results_found_++;
1250 #endif
1251 g_free(buffer);
1252 }
1253 }
1254 }
1255 }
1256
1257
1258
1259
1260
1261 //}
1262
1263
1264 }
1265 }
1266 }
1267 map_rect_destroy(mr);
1268 }
1269 }
1270 }
1271 }
1272 }
1273 map_selection_destroy(sel);
1274 mapset_close(msh);
1275
1276 if (hn_fold)
1277 {
1278 g_free(hn_fold);
1279 }
1280
1281 if (street_name_fold)
1282 {
1283 g_free(street_name_fold);
1284 }
1285
1286
1287 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1288 g_mem_profile();
1289 #endif
1290
1291 return search_results_found_;
1292 }
1293
1294 static GList *
1295 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)
1296 {
1297 struct search_list_result *slr;
1298 struct coord_geo g;
1299 struct coord c;
1300
1301 //// dbg(0,"enter\n");
1302
1303 while ((slr = search_list_get_result(sl)))
1304 {
1305
1306 if (offline_search_break_searching == 1)
1307 {
1308 break;
1309 }
1310
1311 // does the streetname of the housenumber match the street we want?
1312 if (slr != NULL)
1313 {
1314 if (slr->street != NULL)
1315 {
1316 if ((street_name != NULL) && (slr->street->name != NULL))
1317 {
1318 if (strcmp(slr->street->name, street_name) == 0)
1319 {
1320 char *buffer;
1321 // coords of result
1322 c.x = slr->house_number->common.c->x;
1323 c.y = slr->house_number->common.c->y;
1324 transform_to_geo(slr->house_number->common.c->pro, &c, &g);
1325 // SHN -> street with house number
1326 // return a string like: "SHN:H111L5555:16.766:48.76:full address name is at the end"
1327 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 max. 15 chars -> this sould be max. about 335 chars long
1328 if (slr->town->common.postal == NULL)
1329 {
1330 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);
1331 }
1332 else
1333 {
1334 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);
1335 }
1336
1337 //// dbg(0,"res=%s\n",buffer);
1338
1339 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1340 #ifdef HAVE_API_ANDROID
1341 // return results to android as they come in ...
1342 android_return_search_result(jni,buffer);
1343 #endif
1344 g_free(buffer);
1345 }
1346 }
1347 }
1348 }
1349 }
1350
1351 return result_list;
1352 }
1353
1354 static GList *
1355 search_address__street(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, GList *exclude3, int partial, struct jni_object *jni)
1356 {
1357 //// dbg(0,"enter\n");
1358
1359 struct search_list_result *slr = NULL;
1360 GList *tmp = phrases;
1361 int count = 0;
1362 struct coord_geo g;
1363 struct coord c;
1364 struct attr attr2;
1365
1366 struct item *save_item;
1367 int save_level;
1368 int save_last_result_valid;
1369
1370 while ((slr = search_list_get_result(sl)))
1371 {
1372 char *buffer;
1373 char *buffer2;
1374
1375 if (offline_search_break_searching == 1)
1376 {
1377 break;
1378 }
1379
1380 if (slr->street)
1381 {
1382 // coords of result
1383 c.x = slr->street->common.c->x;
1384 c.y = slr->street->common.c->y;
1385 transform_to_geo(slr->street->common.c->pro, &c, &g);
1386
1387 // STR -> street
1388 // return a string like: "STR:H1111L5555:16.766:-48.76:full address name is at the end"
1389 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 chars -> this sould be max. about 320 chars long
1390 if (slr->town->common.postal == NULL)
1391 {
1392 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);
1393 }
1394 else
1395 {
1396 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);
1397 }
1398 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1399
1400 //// dbg(0,"res=%s\n",buffer);
1401
1402 #ifdef HAVE_API_ANDROID
1403 // return results to android as they come in ...
1404 android_return_search_result(jni,buffer);
1405 #endif
1406 count++;
1407
1408 buffer2 = g_strdup_printf("%s", slr->street->name);
1409 //// dbg(0,"b2:%s\n",buffer2);
1410
1411
1412 save_item = sl->item;
1413 save_level = sl->level;
1414 save_last_result_valid = sl->last_result_valid;
1415
1416 #if 1
1417 // put words back to start!!
1418 tmp = phrases;
1419 while (tmp)
1420 {
1421 if (offline_search_break_searching == 1)
1422 {
1423 break;
1424 }
1425
1426 //// dbg(0,"s0=%s\n",tmp->data);
1427 if (tmp != exclude1 && tmp != exclude2 && tmp != exclude3)
1428 {
1429 //// dbg(0,"s=%s\n",tmp->data);
1430
1431 attr2.type = attr_house_number;
1432 attr2.u.str = tmp->data;
1433 search_list_search(sl, &attr2, partial);
1434 result_list = search_address_housenumber_real(result_list, sl, buffer2, phrases, exclude1, exclude2, exclude3, partial, jni);
1435 }
1436 tmp = g_list_next(tmp);
1437 }
1438 #endif
1439
1440 // restore again
1441 sl->item = save_item;
1442 sl->level = save_level;
1443 sl->last_result_valid = save_last_result_valid;
1444
1445 }
1446
1447 if (buffer2)
1448 {
1449 g_free(buffer2);
1450 }
1451
1452 if (buffer)
1453 {
1454 g_free(buffer);
1455 }
1456 }
1457
1458 //// dbg(0,"return 2\n");
1459 return result_list;
1460 }
1461
1462 static GList *
1463 search_address__town(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, int partial, struct jni_object *jni)
1464 {
1465 //// dbg(0,"enter\n");
1466 struct search_list_result *slr;
1467 GList *tmp = phrases;
1468 int count = 0;
1469 struct coord_geo g;
1470 struct coord c;
1471 struct attr attr;
1472 struct attr attrx;
1473 // struct search_list *sl2=search_list_new(sl->ms);
1474 struct item *save_item;
1475 int save_level;
1476 int save_last_result_valid;
1477 // int first=1;
1478
1479 while ((slr = search_list_get_result(sl)))
1480 {
1481 char *buffer;
1482
1483 if (offline_search_break_searching == 1)
1484 {
1485 break;
1486 }
1487
1488 // coords of result
1489 c.x = slr->town->common.c->x;
1490 c.y = slr->town->common.c->y;
1491 transform_to_geo(slr->town->common.c->pro, &c, &g);
1492
1493 // TWN -> town
1494 if (slr->town->common.postal == NULL)
1495 {
1496 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);
1497 }
1498 else
1499 {
1500 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);
1501 }
1502
1503 //// dbg(0,"**res=%s\n",buffer);
1504
1505 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1506 #ifdef HAVE_API_ANDROID
1507 // return results to android as they come in ...
1508 android_return_search_result(jni,buffer);
1509 #endif
1510
1511 count++;
1512 if (buffer)
1513 {
1514 g_free(buffer);
1515 }
1516
1517 save_item = sl->item;
1518 save_level = sl->level;
1519 save_last_result_valid = sl->last_result_valid;
1520
1521 // put words back to start!!
1522 tmp = phrases;
1523
1524 while (tmp)
1525 {
1526 if (offline_search_break_searching == 1)
1527 {
1528 break;
1529 }
1530
1531 if (tmp != exclude1 && tmp != exclude2)
1532 {
1533 //// dbg(0,"s=%s\n",tmp->data);
1534 attr.type = attr_street_name;
1535 attr.u.str = tmp->data;
1536 search_list_search(sl, &attr, partial);
1537 result_list = search_address__street(result_list, sl, phrases, exclude1, exclude2, tmp, partial, jni);
1538 }
1539 tmp = g_list_next(tmp);
1540 }
1541
1542 // restore again
1543 sl->item = save_item;
1544 sl->level = save_level;
1545 sl->last_result_valid = save_last_result_valid;
1546 }
1547
1548 //// dbg(0,"return 2\n");
1549 return result_list;
1550 }
1551
1552 static GList *
1553 search_address__country(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude, int partial, struct jni_object *jni)
1554 {
1555 GList *tmp = phrases;
1556 int count = 0;
1557 struct attr attr;
1558 struct search_list_result *slr;
1559 //// dbg(0,"enter\n");
1560
1561 while ((slr = search_list_get_result(sl)))
1562 {
1563 //// dbg(0,"1 slr=%p\n",slr->country);
1564 //// dbg(0,"2 slr=%s\n",slr->country->name);
1565 //// dbg(0,"3 slr=%s\n",slr->country->iso2);
1566 count++;
1567 }
1568 //// dbg(0,"count %d\n",count);
1569 if (!count)
1570 {
1571 //// dbg(0,"return 1");
1572 return result_list;
1573 }
1574
1575 while (tmp)
1576 {
1577 if (tmp != exclude)
1578 {
1579 //// dbg(0,"Is=%s\n",tmp->data);
1580 attr.type = attr_town_or_district_name;
1581 attr.u.str = tmp->data;
1582 search_list_search(sl, &attr, partial);
1583 result_list = search_address__town(result_list, sl, phrases, exclude, tmp, partial, jni);
1584 }
1585 //else
1586 //{
1587 //// dbg(0,"Xs=%s\n",tmp->data);
1588 //}
1589 tmp = g_list_next(tmp);
1590 }
1591 //// dbg(0,"return 2");
1592 return result_list;
1593 }
1594
1595
1596
1597 struct country2
1598 {
1599 int id;
1600 char *car;
1601 char *iso2;
1602 char *iso3;
1603 char *name;
1604 };
1605
1606 #include "search_countrytable.h"
1607
1608
1609
1610 // @return =0 strings matched, =1 not matched
1611 static int ascii_cmp_local(char *name, char *match, int partial)
1612 {
1613 char *s1_a;
1614 char *s2_a;
1615
1616 char *s1 = linguistics_casefold(name);
1617 char *s2 = linguistics_casefold(match);
1618
1619 if (s1)
1620 {
1621 s1_a = linguistics_remove_all_specials(s1);
1622 if (s1_a)
1623 {
1624 g_free(s1);
1625 s1 = s1_a;
1626 }
1627 s1_a = linguistics_expand_special(s1, 1);
1628 if (s1_a)
1629 {
1630 g_free(s1);
1631 s1 = s1_a;
1632 }
1633 }
1634
1635 if (s2)
1636 {
1637 s2_a = linguistics_remove_all_specials(s2);
1638 if (s2_a)
1639 {
1640 g_free(s2);
1641 s2 = s2_a;
1642 }
1643 s2_a = linguistics_expand_special(s2, 1);
1644 if (s2_a)
1645 {
1646 g_free(s2);
1647 s2 = s2_a;
1648 }
1649 }
1650
1651 int ret = linguistics_compare(s1, s2, partial);
1652
1653 if (s1)
1654 {
1655 g_free(s1);
1656 }
1657
1658 if (s2)
1659 {
1660 g_free(s2);
1661 }
1662
1663 return ret;
1664 }
1665
1666 // @return =0 strings matched, =1 not matched
1667 static int ascii_cmp_local_faster(char *name, char *match, int partial)
1668 {
1669 char *s1_a;
1670 char *s1 = name;
1671 int ret;
1672
1673 s1_a = linguistics_fold_and_prepare_complete(s1, 0);
1674
1675 if (!s1_a)
1676 {
1677 return 1;
1678 }
1679
1680 // dbg(0,"s1=%s match=%s\n", s1_a, match);
1681
1682 if (strlen(s1_a) == 0)
1683 {
1684 // only special chars in string, return "no match"
1685 return 1;
1686 }
1687
1688
1689 // --- old ---
1690 //ret = linguistics_compare(s1, match, partial);
1691 // --- old ---
1692
1693 if (partial == 1)
1694 {
1695 ret = strncmp(s1_a, match, strlen(match));
1696 }
1697 else
1698 {
1699 if (strlen(s1_a) == strlen(match))
1700 {
1701 ret = strncmp(s1_a, match, strlen(match));
1702 }
1703 else
1704 {
1705 ret = 1;
1706 }
1707 }
1708
1709
1710 if (s1_a)
1711 {
1712 g_free(s1_a);
1713 }
1714
1715 return ret;
1716 }
1717
1718 static int ascii_cmp_local_faster_DEBUG(char *name, char *match, int partial)
1719 {
1720 char *s1_a;
1721 char *s1 = name;
1722 int ret;
1723
1724 s1_a = linguistics_fold_and_prepare_complete(s1, 0);
1725
1726 if (!s1_a)
1727 {
1728 dbg(0,"return 001:1\n");
1729 return 1;
1730 }
1731
1732 dbg(0,"s1=%s match=%s\n", s1_a, match);
1733
1734 if (strlen(s1_a) == 0)
1735 {
1736 // only special chars in string, return "no match"
1737 dbg(0,"return 002:1\n");
1738 return 1;
1739 }
1740
1741
1742 // --- old ---
1743 //ret = linguistics_compare(s1, match, partial);
1744 // --- old ---
1745
1746 if (partial == 1)
1747 {
1748 ret = strncmp(s1_a, match, strlen(match));
1749 }
1750 else
1751 {
1752 if (strlen(s1_a) == strlen(match))
1753 {
1754 ret = strncmp(s1_a, match, strlen(match));
1755 }
1756 else
1757 {
1758 ret = 1;
1759 }
1760 }
1761
1762
1763 if (s1_a)
1764 {
1765 g_free(s1_a);
1766 }
1767
1768 dbg(0,"return 099:%d\n", ret);
1769 return ret;
1770 }
1771
1772
1773 struct navit *global_navit;
1774
1775 void search_full_world(char *addr, int partial, int search_order, struct jni_object *jni, struct coord_geo *search_center, int search_radius)
1776 {
1777 struct item *item;
1778 struct map_rect *mr = NULL;
1779 struct mapset *ms;
1780 struct mapset_handle *msh;
1781 struct map* map = NULL;
1782 struct attr map_name_attr;
1783 struct attr attr;
1784
1785 char *str = search_fix_spaces(addr);
1786 GList *phrases = search_split_phrases(str);
1787 GList *phrases_first;
1788 phrases_first = phrases;
1789
1790 ms = global_navit->mapsets->data;
1791 msh = mapset_open(ms);
1792
1793 struct pcoord center99;
1794 int search_radius_this = 0;
1795 // dbg(0, "in lat=%f,lng=%f\n", search_center->lat, search_center->lng);
1796 if ((search_center->lat == 0) && (search_center->lng == 0))
1797 {
1798 center99.x = 0;
1799 center99.y = 0;
1800 search_radius_this = 21000000;
1801 }
1802 else
1803 {
1804 struct coord c99;
1805 transform_from_geo(projection_mg, search_center, &c99);
1806 center99.x = c99.x;
1807 center99.y = c99.y;
1808 search_radius_this = search_radius;
1809 }
1810 // dbg(0, "out x=%d,y=%d,r=%d\n", center99.x, center99.y, search_radius_this);
1811
1812 struct map_selection *sel = map_selection_rect_new(&center99, search_radius_this, search_order);
1813 sel->range.min = type_town_label;
1814 sel->range.max = type_area;
1815
1816 while (msh && (map = mapset_next(msh, 0)))
1817 {
1818 if (offline_search_break_searching == 1)
1819 {
1820 break;
1821 }
1822
1823 if (map_get_attr(map, attr_name, &map_name_attr, NULL))
1824 {
1825 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
1826 {
1827 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/navitmap", map_name_attr.u.str, 43) == 0)
1828 {
1829 // its an sdcard map
1830 //// dbg(0,"map name=%s",map_name_attr.u.str);
1831 // mr=map_rect_new(map, NULL);
1832 mr = map_rect_new(map, sel);
1833 if (mr)
1834 {
1835 char *streetname_last = NULL;
1836
1837 while ((item = map_rect_get_item(mr)))
1838 {
1839
1840 if (offline_search_break_searching == 1)
1841 {
1842 break;
1843 }
1844
1845 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1846 g_mem_profile();
1847 #endif
1848
1849 if ((item_is_town(*item)) || (item_is_district(*item)))
1850 {
1851 struct search_list_town *p = NULL;
1852
1853 if (item_attr_get(item, attr_town_name, &attr))
1854 {
1855 p = search_list_town_new(item);
1856 char *buffer = NULL;
1857 // coords of result
1858 struct coord_geo g;
1859 struct coord c;
1860 c.x = p->common.c->x;
1861 c.y = p->common.c->y;
1862 int calc_geo = 0;
1863
1864 // // dbg(0,"town name=%s\n", attr.u.str);
1865
1866 phrases = phrases_first;
1867 while (phrases)
1868 {
1869
1870 if (offline_search_break_searching == 1)
1871 {
1872 break;
1873 }
1874
1875 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1876 {
1877 // // dbg(0,"matched town name=%s want=%s\n", attr.u.str, phrases->data);
1878 if (calc_geo == 0)
1879 {
1880 transform_to_geo(p->common.c->pro, &c, &g);
1881 // TWN -> town
1882 calc_geo = 1;
1883 }
1884 if (p->common.postal == NULL)
1885 {
1886 buffer = g_strdup_printf("TWN:H%dL%d:%f:%f:%.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.town_name);
1887 }
1888 else
1889 {
1890 buffer = g_strdup_printf("TWN:H%dL%d:%f:%f:%.7s %.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.postal, p->common.town_name);
1891 }
1892 #ifdef HAVE_API_ANDROID
1893 // return results to android as they come in ...
1894 android_return_search_result(jni,buffer);
1895 #endif
1896 }
1897 phrases = g_list_next(phrases);
1898
1899 }
1900
1901 if (buffer)
1902 {
1903 g_free(buffer);
1904 }
1905 search_list_town_destroy(p);
1906 }
1907
1908 if (item_attr_get(item, attr_town_name_match, &attr))
1909 {
1910 p = search_list_town_new(item);
1911 char *buffer = NULL;
1912 // coords of result
1913 struct coord_geo g;
1914 struct coord c;
1915 c.x = p->common.c->x;
1916 c.y = p->common.c->y;
1917 int calc_geo = 0;
1918
1919 // // dbg(0,"town name=%s\n", attr.u.str);
1920
1921 phrases = phrases_first;
1922 while (phrases)
1923 {
1924 if (offline_search_break_searching == 1)
1925 {
1926 break;
1927 }
1928
1929 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1930 {
1931 // // dbg(0,"matched town name=%s want=%s\n", attr.u.str, phrases->data);
1932 if (calc_geo == 0)
1933 {
1934 transform_to_geo(p->common.c->pro, &c, &g);
1935 // TWN -> town
1936 calc_geo = 1;
1937 }
1938 if (p->common.postal == NULL)
1939 {
1940 buffer = g_strdup_printf("TWN:H%dL%d:%f:%f:%.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.town_name);
1941 }
1942 else
1943 {
1944 buffer = g_strdup_printf("TWN:H%dL%d:%f:%f:%.7s %.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.postal, p->common.town_name);
1945 }
1946 #ifdef HAVE_API_ANDROID
1947 // return results to android as they come in ...
1948 android_return_search_result(jni,buffer);
1949 #endif
1950 }
1951 phrases = g_list_next(phrases);
1952
1953 }
1954
1955 if (buffer)
1956 {
1957 g_free(buffer);
1958 }
1959 search_list_town_destroy(p);
1960 }
1961 }
1962 else if (item_is_street(*item))
1963 {
1964
1965 struct search_list_street *p = NULL;
1966
1967 if (item_attr_get(item, attr_label, &attr))
1968 {
1969 // // dbg(0,"street1=%s\n",map_convert_string(item->map, attr.u.str));
1970 if ((streetname_last == NULL) || (strcmp(streetname_last, attr.u.str) != 0))
1971 {
1972 // // dbg(0,"street2=%s\n",map_convert_string(item->map, attr.u.str));
1973 streetname_last = g_strdup_printf("%s", attr.u.str);
1974
1975 p = search_list_street_new(item);
1976 char *buffer = NULL;
1977 // coords of result
1978 struct coord_geo g;
1979 struct coord c;
1980 c.x = p->common.c->x;
1981 c.y = p->common.c->y;
1982 int calc_geo = 0;
1983
1984 phrases = phrases_first;
1985 while (phrases)
1986 {
1987 if (offline_search_break_searching == 1)
1988 {
1989 break;
1990 }
1991
1992 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1993 {
1994 if (calc_geo == 0)
1995 {
1996 transform_to_geo(p->common.c->pro, &c, &g);
1997 calc_geo = 1;
1998 }
1999 if (p->common.postal == NULL)
2000 {
2001 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, attr.u.str);
2002 }
2003 else
2004 {
2005 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.7s %.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.postal, attr.u.str);
2006 }
2007 //// dbg(0,"street3=%s\n",buffer);
2008 #ifdef HAVE_API_ANDROID
2009 // return results to android as they come in ...
2010 android_return_search_result(jni,buffer);
2011 #endif
2012 }
2013 phrases = g_list_next(phrases);
2014 }
2015 if (buffer)
2016 {
2017 g_free(buffer);
2018 }
2019 search_list_street_destroy(p);
2020 }
2021 }
2022
2023 if (item_attr_get(item, attr_street_name_match, &attr))
2024 {
2025 //// dbg(0,"street systematic=%s\n",map_convert_string(item->map, attr.u.str));
2026
2027 p = search_list_street_new(item);
2028 char *buffer = NULL;
2029 // coords of result
2030 struct coord_geo g;
2031 struct coord c;
2032 c.x = p->common.c->x;
2033 c.y = p->common.c->y;
2034 int calc_geo = 0;
2035
2036 phrases = phrases_first;
2037 while (phrases)
2038 {
2039 if (offline_search_break_searching == 1)
2040 {
2041 break;
2042 }
2043
2044 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
2045 {
2046 if (calc_geo == 0)
2047 {
2048 transform_to_geo(p->common.c->pro, &c, &g);
2049 calc_geo = 1;
2050 }
2051 if (p->common.postal == NULL)
2052 {
2053 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, attr.u.str);
2054 }
2055 else
2056 {
2057 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.7s %.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.postal, attr.u.str);
2058 }
2059 #ifdef HAVE_API_ANDROID
2060 // return results to android as they come in ...
2061 android_return_search_result(jni,buffer);
2062 #endif
2063 }
2064 phrases = g_list_next(phrases);
2065 }
2066 if (buffer)
2067 {
2068 g_free(buffer);
2069 }
2070 search_list_street_destroy(p);
2071
2072 }
2073
2074 if (item_attr_get(item, attr_street_name_systematic, &attr))
2075 {
2076 //// dbg(0,"street systematic=%s\n",map_convert_string(item->map, attr.u.str));
2077
2078 p = search_list_street_new(item);
2079 char *buffer = NULL;
2080 // coords of result
2081 struct coord_geo g;
2082 struct coord c;
2083 c.x = p->common.c->x;
2084 c.y = p->common.c->y;
2085 int calc_geo = 0;
2086
2087 phrases = phrases_first;
2088 while (phrases)
2089 {
2090 if (offline_search_break_searching == 1)
2091 {
2092 break;
2093 }
2094
2095 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
2096 {
2097 if (calc_geo == 0)
2098 {
2099 transform_to_geo(p->common.c->pro, &c, &g);
2100 calc_geo = 1;
2101 }
2102 if (p->common.postal == NULL)
2103 {
2104 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, attr.u.str);
2105 }
2106 else
2107 {
2108 buffer = g_strdup_printf("STR:H%dL%d:%f:%f:%.7s %.101s", p->common.item.id_hi, p->common.item.id_lo, g.lat, g.lng, p->common.postal, attr.u.str);
2109 }
2110 #ifdef HAVE_API_ANDROID
2111 // return results to android as they come in ...
2112 android_return_search_result(jni,buffer);
2113 #endif
2114 }
2115 phrases = g_list_next(phrases);
2116 }
2117 if (buffer)
2118 {
2119 g_free(buffer);
2120 }
2121 search_list_street_destroy(p);
2122
2123 }
2124 }
2125 }
2126 g_free(streetname_last);
2127 map_rect_destroy(mr);
2128 }
2129 }
2130 }
2131 }
2132 }
2133
2134 map_selection_destroy(sel);
2135
2136 if (phrases)
2137 {
2138 g_list_free(phrases);
2139 }
2140 g_free(str);
2141
2142 mapset_close(msh);
2143
2144 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
2145 g_mem_profile();
2146 #endif
2147 }
2148
2149 GList *
2150 search_by_address(GList *result_list, struct mapset *ms, char *addr, int partial, struct jni_object *jni, int search_country_flags, char *search_country_string)
2151 {
2152 char *str = search_fix_spaces(addr);
2153 GList *tmp, *phrases = search_split_phrases(str);
2154 GList *phrases_first;
2155 GList *ret = NULL;
2156 struct search_list *sl;
2157 struct attr attr;
2158 attr.type = attr_country_all;
2159 tmp = phrases;
2160 phrases_first = phrases;
2161 sl = search_list_new(ms);
2162
2163 // dbg(0, "-- START --\n");
2164
2165 // normal search stuff -------- START ----------
2166 if (search_country_flags == 1)
2167 {
2168 // dbg(0, "-- country default start --\n");
2169 //while (phrases)
2170 //{
2171 // // dbg(0,"s=%s\n",phrases->data);
2172 // set default country
2173 search_list_search(sl, country_default(), 0);
2174 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2175 // phrases=g_list_next(phrases);
2176 //}
2177 // dbg(0, "-- country default end --\n");
2178 }
2179 else if (search_country_flags == 2)
2180 {
2181 // dbg(0, "-- country sel:%s start --\n", search_country_string);
2182 // set a country
2183 struct attr country;
2184 country.type = attr_country_iso2;
2185 country.u.str = search_country_string;
2186 //while (phrases)
2187 //{
2188 // // dbg(0,"s=%s\n",phrases->data);
2189 search_list_search(sl, &country, 0);
2190 // set a country
2191 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2192 //phrases=g_list_next(phrases);
2193 //}
2194 // dbg(0, "-- country sel:%s end --\n", search_country_string);
2195 }
2196 else // flags==3
2197 {
2198 // dbg(0, "-- country all start --\n");
2199 // search all countries!! could take a really long time!!
2200 struct attr country;
2201 int j2 = sizeof(all_country_list) / sizeof(all_country_list[0]);
2202 int j1;
2203 for (j1 = 0; j1 < j2; j1++)
2204 {
2205 if (all_country_list[j1].iso2 != NULL)
2206 {
2207 phrases = phrases_first;
2208 //while (phrases)
2209 //{
2210 // // dbg(0,"s country=%s\n",all_country_list[j1].iso2);
2211 // // dbg(0,"s=%s\n",phrases->data);
2212 country.type = attr_country_iso2;
2213 country.u.str = all_country_list[j1].iso2;
2214 search_list_search(sl, &country, 0);
2215 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2216 //phrases=g_list_next(phrases);
2217 //}
2218
2219 if (offline_search_break_searching == 1)
2220 {
2221 break;
2222 }
2223 }
2224 }
2225 // dbg(0, "-- country all end --\n");
2226 }
2227 // normal search stuff -------- END ----------
2228
2229 if (phrases_first)
2230 {
2231 g_list_free(phrases_first);
2232 }
2233
2234 // dbg(0, "-- END --\n");
2235
2236 g_free(str);
2237 return ret;
2238 }
2239
2240
2241
2242
2243

   
Visit the ZANavi Wiki