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

Contents of /navit/navit/search.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 90800 byte(s)
new map version, lots of fixes and experimental new features
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 struct search_list_level
62 {
63 struct mapset *ms;
64 struct search_list_common *parent;
65 struct attr *attr;
66 int partial;
67 int selected;
68 struct mapset_search *search;
69 GHashTable *hash;
70 GList *list, *curr, *last;
71 };
72
73 struct interpolation
74 {
75 int side, mode, rev;
76 char *first, *last, *curr;
77 };
78
79 struct search_list
80 {
81 struct mapset *ms;
82 struct item *item;
83 int level;
84 struct search_list_level levels[4];
85 struct search_list_result result;
86 struct search_list_result last_result;
87 int last_result_valid;
88 char *postal;
89 struct interpolation inter;
90 };
91
92 // func definition
93 static int ascii_cmp_local_faster(char *name, char *match, int partial);
94 // func definition
95
96 static guint search_item_hash_hash(gconstpointer key)
97 {
98 const struct item *itm = key;
99 gconstpointer hashkey = (gconstpointer) GINT_TO_POINTER(itm->id_hi ^ itm->id_lo);
100 return g_direct_hash(hashkey);
101 }
102
103 static gboolean search_item_hash_equal(gconstpointer a, gconstpointer b)
104 {
105 const struct item *itm_a = a;
106 const struct item *itm_b = b;
107 if (item_is_equal_id(*itm_a, *itm_b))
108 return TRUE;
109 return FALSE;
110 }
111
112 struct search_list *
113 search_list_new(struct mapset *ms)
114 {
115 struct search_list *ret;
116
117 ret=g_new0(struct search_list, 1);
118 ret->ms = ms;
119
120 return ret;
121 }
122
123 static void search_list_search_free(struct search_list *sl, int level);
124
125 static int search_list_level(enum attr_type attr_type)
126 {
127 switch (attr_type)
128 {
129 case attr_country_all:
130 case attr_country_id:
131 case attr_country_iso2:
132 case attr_country_iso3:
133 case attr_country_car:
134 case attr_country_name:
135 return 0;
136 case attr_town_postal:
137 return 1;
138 case attr_town_name:
139 case attr_district_name:
140 case attr_town_or_district_name:
141 return 1;
142 case attr_street_name:
143 return 2;
144 case attr_house_number:
145 return 3;
146 case attr_postal:
147 return -1;
148 default:
149 // // dbg(0, "unknown search '%s'\n", attr_to_name(attr_type));
150 return -1;
151 }
152 }
153
154 static void interpolation_clear(struct interpolation *inter)
155 {
156 inter->mode = inter->side = 0;
157 g_free(inter->first);
158 g_free(inter->last);
159 g_free(inter->curr);
160 inter->first = inter->last = inter->curr = NULL;
161 }
162
163 void search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
164 {
165 struct search_list_level *le;
166 int level = search_list_level(search_attr->type);
167 this_->item = NULL;
168 interpolation_clear(&this_->inter);
169 //// // dbg(0,"## enter\n");
170 //// dbg(0,"## level=%d\n", level);
171 if (level != -1)
172 {
173 this_->result.id = 0;
174 this_->level = level;
175 le = &this_->levels[level];
176 search_list_search_free(this_, level);
177 le->attr = attr_dup(search_attr);
178 le->partial = partial;
179 if (level > 0)
180 {
181 le = &this_->levels[level - 1];
182 le->curr = le->list;
183 }
184 //// dbg(0,"## le=%p partial=%d\n", le, partial);
185 }
186 else if (search_attr->type == attr_postal)
187 {
188 g_free(this_->postal);
189 this_->postal = g_strdup(search_attr->u.str);
190 }
191 //// dbg(0,"## return\n");
192 }
193
194 struct search_list_common *
195 search_list_select(struct search_list *this_, enum attr_type attr_type, int id, int mode)
196 {
197 int level = search_list_level(attr_type);
198 int num = 0;
199 struct search_list_level *le;
200 struct search_list_common *slc;
201 GList *curr;
202 le = &this_->levels[level];
203 curr = le->list;
204 if (mode > 0 || !id)
205 le->selected = mode;
206 //// dbg(0,"enter level=%d %d %d %p\n", level, id, mode, curr);
207 while (curr)
208 {
209 num++;
210 if (!id || num == id)
211 {
212 slc = curr->data;
213 slc->selected = mode;
214 if (id)
215 {
216 le->last = curr;
217 //// dbg(0,"found\n");
218 return slc;
219 }
220 }
221 curr = g_list_next(curr);
222 }
223 //// dbg(0,"not found\n");
224 return NULL;
225 }
226
227 static void search_list_common_new(struct item *item, struct search_list_common *common)
228 {
229 struct attr attr;
230 if (item_attr_get(item, attr_town_name, &attr))
231 common->town_name = map_convert_string(item->map, attr.u.str);
232 else
233 common->town_name = NULL;
234 if (item_attr_get(item, attr_county_name, &attr))
235 common->county_name = map_convert_string(item->map, attr.u.str);
236 else
237 common->county_name = NULL;
238 if (item_attr_get(item, attr_district_name, &attr))
239 common->district_name = map_convert_string(item->map, attr.u.str);
240 else
241 common->district_name = NULL;
242 if (item_attr_get(item, attr_postal, &attr))
243 common->postal = map_convert_string(item->map, attr.u.str);
244 else if (item_attr_get(item, attr_town_postal, &attr))
245 common->postal = map_convert_string(item->map, attr.u.str);
246 else
247 common->postal = NULL;
248 if (item_attr_get(item, attr_postal_mask, &attr))
249 common->postal_mask = map_convert_string(item->map, attr.u.str);
250 else
251 common->postal_mask = NULL;
252 }
253
254 static void search_list_common_destroy(struct search_list_common *common)
255 {
256 map_convert_free(common->town_name);
257 map_convert_free(common->district_name);
258 map_convert_free(common->county_name);
259 map_convert_free(common->postal);
260 map_convert_free(common->postal_mask);
261 }
262
263 static struct search_list_country *
264 search_list_country_new(struct item *item)
265 {
266 struct search_list_country *ret=g_new0(struct search_list_country, 1);
267 struct attr attr;
268
269 ret->common.item = ret->common.unique = *item;
270 if (item_attr_get(item, attr_country_car, &attr))
271 ret->car = g_strdup(attr.u.str);
272 if (item_attr_get(item, attr_country_iso2, &attr))
273 {
274 #if HAVE_API_ANDROID
275 ret->iso2=g_malloc(strlen(attr.u.str)+1);
276 strtolower(ret->iso2, attr.u.str);
277 #else
278 ret->iso2 = g_strdup(attr.u.str);
279 #endif
280 ret->flag = g_strdup_printf("country_%s", ret->iso2);
281 }
282 if (item_attr_get(item, attr_country_iso3, &attr))
283 ret->iso3 = g_strdup(attr.u.str);
284 if (item_attr_get(item, attr_country_name, &attr))
285 ret->name = g_strdup(attr.u.str);
286 return ret;
287 }
288
289 static void search_list_country_destroy(struct search_list_country *this_)
290 {
291 g_free(this_->car);
292 g_free(this_->iso2);
293 g_free(this_->iso3);
294 g_free(this_->flag);
295 g_free(this_->name);
296 g_free(this_);
297 }
298
299 static struct search_list_town *
300 search_list_town_new(struct item *item)
301 {
302 struct search_list_town *ret=g_new0(struct search_list_town, 1);
303 struct attr attr;
304 struct coord c;
305
306 ret->itemt = *item;
307 ret->common.item = ret->common.unique = *item;
308
309 if (item_attr_get(item, attr_town_streets_item, &attr))
310 {
311 //// dbg(1, "town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo);
312 ret->common.unique = *attr.u.item;
313 }
314
315 search_list_common_new(item, &ret->common);
316
317 if (item_attr_get(item, attr_county_name, &attr))
318 {
319 ret->county = map_convert_string(item->map, attr.u.str);
320 }
321 else
322 {
323 ret->county = NULL;
324 }
325
326 if (item_coord_get(item, &c, 1))
327 {
328 ret->common.c=g_new(struct pcoord, 1);
329 ret->common.c->x = c.x;
330 ret->common.c->y = c.y;
331 ret->common.c->pro = map_projection(item->map);
332 }
333 else
334 {
335 // some error with lat/lng !!
336 // but still return something, or app will crash
337 ret->common.c=g_new(struct pcoord, 1);
338 ret->common.c->x = 0;
339 ret->common.c->y = 0;
340 ret->common.c->pro = map_projection(item->map);
341 }
342 return ret;
343 }
344
345 static void search_list_town_destroy(struct search_list_town *this_)
346 {
347 map_convert_free(this_->county);
348 search_list_common_destroy(&this_->common);
349 if (this_->common.c)
350 g_free(this_->common.c);
351 g_free(this_);
352 }
353
354 static struct search_list_street *
355 search_list_street_new(struct item *item)
356 {
357 struct search_list_street *ret=g_new0(struct search_list_street, 1);
358 struct attr attr;
359 struct coord c;
360
361 ret->common.item = ret->common.unique = *item;
362 if (item_attr_get(item, attr_street_name, &attr))
363 {
364 ret->name = map_convert_string(item->map, attr.u.str);
365 }
366 else
367 {
368 ret->name = NULL;
369 }
370 search_list_common_new(item, &ret->common);
371 if (item_coord_get(item, &c, 1))
372 {
373 ret->common.c=g_new(struct pcoord, 1);
374 ret->common.c->x = c.x;
375 ret->common.c->y = c.y;
376 ret->common.c->pro = map_projection(item->map);
377 }
378 else
379 {
380 // some error with lat/lng !!
381 // but still return something, or app will crash
382 ret->common.c=g_new(struct pcoord, 1);
383 ret->common.c->x = 0;
384 ret->common.c->y = 0;
385 ret->common.c->pro = map_projection(item->map);
386 }
387 return ret;
388 }
389
390 static void search_list_street_destroy(struct search_list_street *this_)
391 {
392 map_convert_free(this_->name);
393 search_list_common_destroy(&this_->common);
394 if (this_->common.c)
395 {
396 g_free(this_->common.c);
397 }
398 g_free(this_);
399 }
400
401 static char *
402 search_interpolate(struct interpolation *inter)
403 {
404 // dbg(1, "interpolate %s-%s %s\n", inter->first, inter->last, inter->curr);
405 if (!inter->first || !inter->last)
406 return NULL;
407 if (!inter->curr)
408 inter->curr = g_strdup(inter->first);
409 else
410 {
411 if (strcmp(inter->curr, inter->last))
412 {
413 int next = atoi(inter->curr) + (inter->mode ? 2 : 1);
414 g_free(inter->curr);
415 if (next == atoi(inter->last))
416 inter->curr = g_strdup(inter->last);
417 else
418 inter->curr = g_strdup_printf("%d", next);
419 }
420 else
421 {
422 g_free(inter->curr);
423 inter->curr = NULL;
424 }
425 }
426 // dbg(1, "interpolate result %s\n", inter->curr);
427 return inter->curr;
428 }
429
430 static void search_interpolation_split(char *str, struct interpolation *inter)
431 {
432 char *pos = strchr(str, '-');
433 char *first, *last;
434 int len;
435 if (!pos)
436 {
437 inter->first = g_strdup(str);
438 inter->last = g_strdup(str);
439 inter->rev = 0;
440 return;
441 }
442 len = pos - str;
443 first = g_malloc(len + 1);
444 strncpy(first, str, len);
445 first[len] = '\0';
446 last = g_strdup(pos + 1);
447 // dbg(1, "%s = %s - %s\n", str, first, last);
448 if (atoi(first) > atoi(last))
449 {
450 inter->first = last;
451 inter->last = first;
452 inter->rev = 1;
453 }
454 else
455 {
456 inter->first = first;
457 inter->last = last;
458 inter->rev = 0;
459 }
460 }
461
462 static int search_setup_interpolation(struct item *item, enum attr_type i0, enum attr_type i1, enum attr_type i2, struct interpolation *inter)
463 {
464 struct attr attr;
465 g_free(inter->first);
466 g_free(inter->last);
467 g_free(inter->curr);
468 inter->first = inter->last = inter->curr = NULL;
469 // dbg(1, "setup %s\n", attr_to_name(i0));
470 if (item_attr_get(item, i0, &attr))
471 {
472 search_interpolation_split(attr.u.str, inter);
473 inter->mode = 0;
474 }
475 else if (item_attr_get(item, i1, &attr))
476 {
477 search_interpolation_split(attr.u.str, inter);
478 inter->mode = 1;
479 }
480 else if (item_attr_get(item, i2, &attr))
481 {
482 search_interpolation_split(attr.u.str, inter);
483 inter->mode = 2;
484 }
485 else
486 return 0;
487 return 1;
488 }
489
490 static int search_match(char *str, char *search, int partial)
491 {
492 if (!partial)
493 return (!g_strcasecmp(str, search));
494 else
495 return (!g_strncasecmp(str, search, strlen(search)));
496 }
497
498 static struct pcoord *
499 search_house_number_coordinate(struct item *item, struct interpolation *inter)
500 {
501 struct pcoord *ret=g_new(struct pcoord, 1);
502 ret->pro = map_projection(item->map);
503
504 // // dbg(0,"001t: %s\n", item_to_name(item->type));
505
506 if (item_is_point(*item))
507 {
508 struct coord c;
509 if (item_coord_get(item, &c, 1))
510 {
511 ret->x = c.x;
512 ret->y = c.y;
513 }
514 else
515 {
516 g_free(ret);
517 ret = NULL;
518 }
519 }
520 else
521 {
522 int count, max = 1024;
523 int hn_pos, hn_length;
524 struct coord *c = g_alloca(sizeof(struct coord) * max);
525 item_coord_rewind(item);
526 count = item_coord_get(item, c, max);
527 hn_length = atoi(inter->last) - atoi(inter->first);
528 if (inter->rev)
529 hn_pos = atoi(inter->last) - atoi(inter->curr);
530 else
531 hn_pos = atoi(inter->curr) - atoi(inter->first);
532
533 if (count)
534 {
535 int i, distance_sum = 0, hn_distance;
536 int *distances = g_alloca(sizeof(int) * (count - 1));
537 // 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);
538 if (!hn_length)
539 {
540 hn_length = 2;
541 hn_pos = 1;
542 }
543 if (count == max)
544 // dbg(0, "coordinate overflow\n");
545 for (i = 0; i < count - 1; i++)
546 {
547 distances[i] = navit_sqrt(transform_distance_sq(&c[i], &c[i + 1]));
548 distance_sum += distances[i];
549 // dbg(1, "distance[%d]=%d\n", i, distances[i]);
550 }
551 // dbg(1, "sum=%d\n", distance_sum);
552 hn_distance = distance_sum * hn_pos / hn_length;
553 // dbg(1, "hn_distance=%d\n", hn_distance);
554 i = 0;
555 while (i < count - 1 && hn_distance > distances[i])
556 hn_distance -= distances[i++];
557 // dbg(1, "remaining distance=%d from %d\n", hn_distance, distances[i]);
558 ret->x = (c[i + 1].x - c[i].x) * hn_distance / distances[i] + c[i].x;
559 ret->y = (c[i + 1].y - c[i].y) * hn_distance / distances[i] + c[i].y;
560 }
561 }
562 return ret;
563 }
564
565 static struct search_list_house_number *
566 search_list_house_number_new(struct item *item, struct interpolation *inter, char *inter_match, int inter_partial)
567 {
568 struct search_list_house_number *ret=g_new0(struct search_list_house_number, 1);
569 struct attr attr;
570 char *hn;
571
572 //// dbg(0,"@@@@ enter @@@@\n");
573
574 ret->common.item = ret->common.unique = *item;
575 //if (item_attr_get(item, attr_street_name, &attr))
576 // // dbg(0,"xx1 %s\n",attr.u.str);
577 if (item_attr_get(item, attr_house_number, &attr))
578 {
579 ret->house_number = map_convert_string(item->map, attr.u.str);
580 }
581 else
582 {
583 //if (item_attr_get(item, attr_street_name, &attr))
584 // // dbg(0,"xx2 %s\n",attr.u.str);
585 for (;;)
586 {
587 //// dbg(0,"interpolate 11");
588 ret->interpolation = 1;
589 switch (inter->side)
590 {
591 case 0:
592 //// dbg(0,"interpolate 11 0");
593 inter->side = -1;
594 search_setup_interpolation(item, attr_house_number_left, attr_house_number_left_odd, attr_house_number_left_even, inter);
595 case -1:
596 //// dbg(0,"interpolate 11 -1");
597 if ((hn = search_interpolate(inter)))
598 break;
599 inter->side = 1;
600 search_setup_interpolation(item, attr_house_number_right, attr_house_number_right_odd, attr_house_number_right_even, inter);
601 case 1:
602 //// dbg(0,"interpolate 11 1");
603 if ((hn = search_interpolate(inter)))
604 break;
605 default:
606 //// dbg(0,"interpolate 11 default");
607 g_free(ret);
608 return NULL;
609 }
610 if (search_match(hn, inter_match, inter_partial))
611 {
612 //// dbg(0,"interpolate 22");
613 //// dbg(0,"match %s %s-%s\n",hn, inter->first, inter->last);
614 ret->house_number = map_convert_string(item->map, hn);
615 break;
616 }
617 }
618 }
619 search_list_common_new(item, &ret->common);
620 ret->common.c = search_house_number_coordinate(item, ret->interpolation ? inter : NULL);
621 return ret;
622 }
623
624 static void search_list_house_number_destroy(struct search_list_house_number *this_)
625 {
626 map_convert_free(this_->house_number);
627 search_list_common_destroy(&this_->common);
628 if (this_->common.c)
629 g_free(this_->common.c);
630 g_free(this_);
631 }
632
633 static void search_list_result_destroy(int level, void *p)
634 {
635 switch (level)
636 {
637 case 0:
638 search_list_country_destroy(p);
639 break;
640 case 1:
641 search_list_town_destroy(p);
642 break;
643 case 2:
644 search_list_street_destroy(p);
645 break;
646 case 3:
647 search_list_house_number_destroy(p);
648 break;
649 }
650 }
651
652 static void search_list_search_free(struct search_list *sl, int level)
653 {
654 //// dbg(0,"enter\n");
655
656 struct search_list_level *le = &sl->levels[level];
657 GList *next, *curr;
658 if (le->search)
659 {
660 mapset_search_destroy(le->search);
661 le->search = NULL;
662 }
663 #if 0 /* FIXME */
664 if (le->hash)
665 {
666 g_hash_table_destroy(le->hash);
667 le->hash=NULL;
668 }
669 #endif
670 curr = le->list;
671 while (curr)
672 {
673 search_list_result_destroy(level, curr->data);
674 next = g_list_next(curr);
675 curr = next;
676 }
677 attr_free(le->attr);
678 g_list_free(le->list);
679 le->list = NULL;
680 le->curr = NULL;
681 le->last = NULL;
682
683 //// dbg(0,"return\n");
684 }
685
686 char *
687 search_postal_merge(char *mask, char *new)
688 {
689 int i;
690 char *ret = NULL;
691 // dbg(1, "enter %s %s\n", mask, new);
692 if (!new)
693 return NULL;
694 if (!mask)
695 return g_strdup(new);
696 i = 0;
697 while (mask[i] && new[i])
698 {
699 if (mask[i] != '.' && mask[i] != new[i])
700 break;
701 i++;
702
703 }
704 if (mask[i])
705 {
706 ret = g_strdup(mask);
707 while (mask[i])
708 ret[i++] = '.';
709 }
710 // dbg(1, "merged %s with %s as %s\n", mask, new, ret);
711 return ret;
712 }
713
714 char *
715 search_postal_merge_replace(char *mask, char *new)
716 {
717 char *ret = search_postal_merge(mask, new);
718 if (!ret)
719 return mask;
720 g_free(mask);
721 return ret;
722 }
723
724 static int postal_match(char *postal, char *mask)
725 {
726 for (;;)
727 {
728 if ((*postal != *mask) && (*mask != '.'))
729 return 0;
730 if (!*postal)
731 {
732 if (!*mask)
733 return 1;
734 else
735 return 0;
736 }
737 postal++;
738 mask++;
739 }
740 }
741
742 static int search_add_result(struct search_list_level *le, struct search_list_common *slc)
743 {
744 struct search_list_common *slo;
745 char *merged;
746
747 //// dbg(0,"enter\n");
748
749 //slo=g_hash_table_lookup(le->hash, &slc->unique);
750 //if (!slo) {
751 //g_hash_table_insert(le->hash, &slc->unique, slc);
752 if (slc->postal && !slc->postal_mask)
753 {
754 slc->postal_mask = g_strdup(slc->postal);
755 }
756 // ******
757 g_list_free(le->list);
758 le->list = NULL;
759 // ******
760 le->list = g_list_append(le->list, slc);
761 return 1;
762 //}
763 merged = search_postal_merge(slo->postal_mask, slc->postal);
764 if (merged)
765 {
766 g_free(slo->postal_mask);
767 slo->postal_mask = merged;
768 }
769 return 0;
770 }
771
772 struct search_list_result *
773 search_list_get_result(struct search_list *this_)
774 {
775 struct search_list_level *le, *leu;
776 int level = this_->level;
777 struct attr attr2;
778 int has_street_name = 0;
779
780 //// dbg(0,"******* enter *******\n");
781 le = &this_->levels[level];
782 //// dbg(0,"le=%p\n", le);
783 for (;;)
784 {
785 //// dbg(0,"le->search=%p\n", le->search);
786 if (!le->search)
787 {
788 //// dbg(0,"partial=%d level=%d\n", le->partial, level);
789 if (!level)
790 le->parent = NULL;
791 else
792 {
793 leu = &this_->levels[level - 1];
794 //// dbg(0,"leu->curr=%p\n", leu->curr);
795 for (;;)
796 {
797 //// dbg(0,"*********########");
798
799 struct search_list_common *slc;
800 if (!leu->curr)
801 {
802 return NULL;
803 }
804 le->parent = leu->curr->data;
805 leu->last = leu->curr;
806 leu->curr = g_list_next(leu->curr);
807 slc = (struct search_list_common *) (le->parent);
808 if (!slc)
809 break;
810 if (slc->selected == leu->selected)
811 break;
812 }
813 }
814 #if 0
815 if (le->parent)
816 {
817 // dbg(0,"mapset_search_new with item(%d,%d)\n", le->parent->item.id_hi, le->parent->item.id_lo);
818 }
819 else
820 {
821 // dbg(0,"NO parent!!\n");
822 }
823 // dbg(0,"############## attr=%s\n", attr_to_name(le->attr->type));
824 #endif
825 le->search = mapset_search_new(this_->ms, &le->parent->item, le->attr, le->partial);
826 // ** DOC ** mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial)
827 le->hash = g_hash_table_new(search_item_hash_hash, search_item_hash_equal);
828 }
829
830 //// dbg(0,"le->search=%p\n", le->search);
831
832 if (!this_->item)
833 {
834 //// dbg(0,"sssss 1");
835 this_->item = mapset_search_get_item(le->search);
836 //// dbg(0,"sssss 1 %p\n",this_->item);
837 }
838
839 if (this_->item)
840 {
841 void *p = NULL;
842 //// dbg(0,"id_hi=%d id_lo=%d\n", this_->item->id_hi, this_->item->id_lo);
843 if (this_->postal)
844 {
845 struct attr postal;
846 if (item_attr_get(this_->item, attr_postal_mask, &postal))
847 {
848 if (!postal_match(this_->postal, postal.u.str))
849 continue;
850 }
851 else if (item_attr_get(this_->item, attr_postal, &postal))
852 {
853 if (strcmp(this_->postal, postal.u.str))
854 continue;
855 }
856 }
857 this_->result.country = NULL;
858 this_->result.town = NULL;
859 this_->result.street = NULL;
860 this_->result.c = NULL;
861 //// dbg(0,"case x LEVEL start %d\n",level);
862 switch (level)
863 {
864 case 0:
865 //// dbg(0,"case 0 COUNTRY");
866 p = search_list_country_new(this_->item);
867 this_->result.country = p;
868 this_->result.country->common.parent = NULL;
869 this_->item = NULL;
870 break;
871 case 1:
872 //// dbg(0,"case 1 TOWN");
873 p = search_list_town_new(this_->item);
874 this_->result.town = p;
875 this_->result.town->common.parent = this_->levels[0].last->data;
876 this_->result.country = this_->result.town->common.parent;
877 this_->result.c = this_->result.town->common.c;
878 this_->item = NULL;
879 break;
880 case 2:
881 //// dbg(0,"case 2 STREET");
882 p = search_list_street_new(this_->item);
883 this_->result.street = p;
884 this_->result.street->common.parent = this_->levels[1].last->data;
885 this_->result.town = this_->result.street->common.parent;
886 this_->result.country = this_->result.town->common.parent;
887 this_->result.c = this_->result.street->common.c;
888 this_->item = NULL;
889 break;
890 case 3:
891 //// dbg(0,"case 3 HOUSENUMBER");
892 has_street_name = 0;
893
894 // if this housenumber has a streetname tag, set the name now
895 if (item_attr_get(this_->item, attr_street_name, &attr2))
896 {
897 // // dbg(0,"streetname: %s\n",attr2.u.str);
898 has_street_name = 1;
899 }
900
901 //// dbg(0,"case 3 XXXX 1\n");
902 p = search_list_house_number_new(this_->item, &this_->inter, le->attr->u.str, le->partial);
903 //// dbg(0,"case 3 XXXX 2\n");
904 if (!p)
905 {
906 interpolation_clear(&this_->inter);
907 this_->item = NULL;
908 continue;
909 }
910 //// dbg(0,"case 3 XXXX 3\n");
911 this_->result.house_number = p;
912 if (!this_->result.house_number->interpolation)
913 {
914 this_->item = NULL;
915 }
916
917 this_->result.house_number->common.parent = this_->levels[2].last->data;
918 this_->result.street = this_->result.house_number->common.parent;
919 this_->result.town = this_->result.street->common.parent;
920 this_->result.country = this_->result.town->common.parent;
921 this_->result.c = this_->result.house_number->common.c;
922
923 //// dbg(0,"case 3 XXXX 4\n");
924 if (has_street_name == 1)
925 {
926 gchar *tmp_name = g_strdup(attr2.u.str);
927 this_->result.street->name = tmp_name;
928 //// dbg(0,"res streetname=%s\n",this_->result.street->name);
929 }
930 else
931 {
932 //
933 // this crashes all the time -> so dont use!
934 //static struct search_list_street null_street;
935 //this_->result.street=&null_street;
936 // this crashes all the time -> so dont use!
937 //
938 this_->result.street->name = NULL;
939 }
940 //// dbg(0,"case 3 XXXX 5\n");
941 break;
942 }
943 // CASE END *********
944
945 //// dbg(0,"case end\n");
946
947 if (p)
948 {
949 if (search_add_result(le, p))
950 {
951 //** this_->result.id++;
952 this_->result.id = 0;
953 //// dbg(0,"++++ return result\n");
954 return &this_->result;
955 }
956 else
957 {
958 search_list_result_destroy(level, p);
959 // return &this_->result;
960 }
961 }
962 }
963 else
964 {
965 mapset_search_destroy(le->search);
966 le->search = NULL;
967 g_hash_table_destroy(le->hash);
968 if (!level)
969 {
970 break;
971 }
972 }
973 }
974 return NULL;
975 }
976
977 void search_list_destroy(struct search_list *this_)
978 {
979 g_free(this_->postal);
980 g_free(this_);
981 }
982
983 void search_init(void)
984 {
985 }
986
987 static char *
988 search_fix_spaces(char *str)
989 {
990 int i;
991 int len = strlen(str);
992 char c, *s, *d, *ret = g_strdup(str);
993
994 for (i = 0; i < len; i++)
995 {
996 if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
997 ret[i] = ' ';
998 }
999 s = ret;
1000 d = ret;
1001 len = 0;
1002 do
1003 {
1004 c = *s++;
1005 if (c != ' ' || len != 0)
1006 {
1007 *d++ = c;
1008 len++;
1009 }
1010 while (c == ' ' && *s == ' ')
1011 s++;
1012 if (c == ' ' && *s == '\0')
1013 {
1014 d--;
1015 len--;
1016 }
1017 }
1018 while (c);
1019 return ret;
1020 }
1021
1022 static GList *
1023 search_split_phrases(char *str)
1024 {
1025 char *tmp, *s, *d;
1026 GList *ret = NULL;
1027 s = str;
1028 do
1029 {
1030 tmp = g_strdup(s);
1031 d = tmp + strlen(s) - 1;
1032 ret = g_list_append(ret, g_strdup(s));
1033 while (d >= tmp)
1034 {
1035 if (*d == ' ')
1036 {
1037 *d = '\0';
1038 ret = g_list_append(ret, g_strdup(tmp));
1039 }
1040 d--;
1041 }
1042 g_free(tmp);
1043 do
1044 {
1045 s++;
1046 if (*s == ' ')
1047 {
1048 s++;
1049 break;
1050 }
1051 }
1052 while (*s != '\0');
1053 }
1054 while (*s != '\0');
1055 return ret;
1056 }
1057
1058 static void 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)
1059 {
1060 struct item *item;
1061 struct map_rect *mr = NULL;
1062 struct mapset *ms;
1063 struct mapset_handle *msh;
1064 struct map* map = NULL;
1065 struct attr map_name_attr;
1066 struct attr attr;
1067 struct pcoord center99;
1068 struct map_selection *sel;
1069 int search_radius_this;
1070 int search_order;
1071 struct attr att;
1072 struct attr att2;
1073 char *town_string2;
1074 char *hn_fold = NULL;
1075 char *street_name_fold = NULL;
1076
1077 ms = global_navit->mapsets->data;
1078 msh = mapset_open(ms);
1079
1080 search_order = 18;
1081 search_radius_this = 20;
1082
1083 hn_fold = linguistics_fold_and_prepare_complete(hn_name_match, 0);
1084 street_name_fold = linguistics_fold_and_prepare_complete(street_name_match, 0);
1085
1086 if (!street_name_fold)
1087 {
1088 return;
1089 }
1090
1091 if (!hn_fold)
1092 {
1093 return;
1094 }
1095
1096 if (strlen(street_name_fold) < 1)
1097 {
1098 if (hn_fold)
1099 {
1100 g_free(hn_fold);
1101 }
1102
1103 if (street_name_fold)
1104 {
1105 g_free(street_name_fold);
1106 }
1107 return;
1108 }
1109
1110 if (strlen(hn_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;
1122 }
1123
1124 if (strlen(town_string) > 100)
1125 {
1126 town_string2 = town_string;
1127 town_string2[101] = '\0';
1128 town_string2 = linguistics_check_utf8_string(town_string2);
1129 }
1130 else
1131 {
1132 town_string2 = town_string;
1133 }
1134
1135
1136 center99.x = c->x;
1137 center99.y = c->y;
1138 sel = map_selection_rect_new(&center99, search_radius_this, search_order);
1139 sel->range.min = type_house_number;
1140 sel->range.max = type_house_number;
1141 sel->u.c_rect.lu.x = center99.x - search_radius_this;
1142 sel->u.c_rect.lu.y = center99.y + search_radius_this;
1143 sel->u.c_rect.rl.x = center99.x + search_radius_this;
1144 sel->u.c_rect.rl.y = center99.y - search_radius_this;
1145
1146 // dbg(0, "hn=%s sn=%s\n", hn_name_match, street_name_match);
1147 // dbg(0, "cx=%d cy=%d\n", c->x, c->y);
1148
1149 while (msh && (map = mapset_next(msh, 0)))
1150 {
1151 if (offline_search_break_searching == 1)
1152 {
1153 break;
1154 }
1155
1156 if (map_get_attr(map, attr_name, &map_name_attr, NULL))
1157 {
1158 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
1159 {
1160 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/navitmap", map_name_attr.u.str, 38) == 0)
1161 {
1162 // its an sdcard map
1163 mr = map_rect_new(map, sel);
1164 if (mr)
1165 {
1166 while ((item = map_rect_get_item(mr)))
1167 {
1168 if (offline_search_break_searching == 1)
1169 {
1170 break;
1171 }
1172
1173 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1174 g_mem_profile();
1175 #endif
1176
1177 if (item->type == type_house_number)
1178 {
1179 // does it have a housenumber?
1180 if (item_attr_get(item, attr_house_number, &att))
1181 {
1182 // match housenumber to our string
1183 if (!ascii_cmp_local_faster(att.u.str, hn_fold, partial))
1184 {
1185 // if this housenumber has a streetname tag, compare it now
1186 if (item_attr_get(item, attr_street_name, &att2))
1187 {
1188 if (!ascii_cmp_local_faster(att2.u.str, street_name_fold, partial))
1189 {
1190 // coords of result
1191 struct coord c2;
1192 char *buffer;
1193
1194 if (item_coord_get(item, &c2, 1))
1195 {
1196 // SHN -> street with house number
1197 // return a string like: "SHN:H111L5555:16.766:48.76:full address name is at the end"
1198 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 max. 15 chars -> this sould be max. about 335 chars long
1199 if (town_string)
1200 {
1201 buffer = g_strdup_printf("SHN:H0L0:%d:%d:%s %s, %.101s", c2.y, c2.x, att2.u.str, att.u.str, town_string);
1202 }
1203 else
1204 {
1205 buffer = g_strdup_printf("SHN:H0L0:%d:%d:%s %s", c2.y, c2.x, att2.u.str, att.u.str);
1206 }
1207
1208 #ifdef HAVE_API_ANDROID
1209 // return results to android as they come in ...
1210 android_return_search_result(jni,buffer);
1211 #endif
1212 g_free(buffer);
1213 }
1214 }
1215 }
1216 }
1217 }
1218 }
1219 }
1220 map_rect_destroy(mr);
1221 }
1222 }
1223 }
1224 }
1225 }
1226 map_selection_destroy(sel);
1227 mapset_close(msh);
1228
1229 if (hn_fold)
1230 {
1231 g_free(hn_fold);
1232 }
1233
1234 if (street_name_fold)
1235 {
1236 g_free(street_name_fold);
1237 }
1238
1239
1240 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1241 g_mem_profile();
1242 #endif
1243 }
1244
1245 static GList *
1246 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)
1247 {
1248 struct search_list_result *slr;
1249 struct coord_geo g;
1250 struct coord c;
1251
1252 //// dbg(0,"enter\n");
1253
1254 while ((slr = search_list_get_result(sl)))
1255 {
1256
1257 if (offline_search_break_searching == 1)
1258 {
1259 break;
1260 }
1261
1262 // does the streetname of the housenumber match the street we want?
1263 if (slr != NULL)
1264 {
1265 if (slr->street != NULL)
1266 {
1267 if ((street_name != NULL) && (slr->street->name != NULL))
1268 {
1269 if (strcmp(slr->street->name, street_name) == 0)
1270 {
1271 char *buffer;
1272 // coords of result
1273 c.x = slr->house_number->common.c->x;
1274 c.y = slr->house_number->common.c->y;
1275 transform_to_geo(slr->house_number->common.c->pro, &c, &g);
1276 // SHN -> street with house number
1277 // return a string like: "SHN:H111L5555:16.766:48.76:full address name is at the end"
1278 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 max. 15 chars -> this sould be max. about 335 chars long
1279 if (slr->town->common.postal == NULL)
1280 {
1281 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);
1282 }
1283 else
1284 {
1285 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);
1286 }
1287
1288 //// dbg(0,"res=%s\n",buffer);
1289
1290 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1291 #ifdef HAVE_API_ANDROID
1292 // return results to android as they come in ...
1293 android_return_search_result(jni,buffer);
1294 #endif
1295 g_free(buffer);
1296 }
1297 }
1298 }
1299 }
1300 }
1301
1302 return result_list;
1303 }
1304
1305 static GList *
1306 search_address__street(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, GList *exclude3, int partial, struct jni_object *jni)
1307 {
1308 //// dbg(0,"enter\n");
1309
1310 struct search_list_result *slr = NULL;
1311 GList *tmp = phrases;
1312 int count = 0;
1313 struct coord_geo g;
1314 struct coord c;
1315 struct attr attr2;
1316
1317 struct item *save_item;
1318 int save_level;
1319 int save_last_result_valid;
1320
1321 while ((slr = search_list_get_result(sl)))
1322 {
1323 char *buffer;
1324 char *buffer2;
1325
1326 if (offline_search_break_searching == 1)
1327 {
1328 break;
1329 }
1330
1331 if (slr->street)
1332 {
1333 // coords of result
1334 c.x = slr->street->common.c->x;
1335 c.y = slr->street->common.c->y;
1336 transform_to_geo(slr->street->common.c->pro, &c, &g);
1337
1338 // STR -> street
1339 // return a string like: "STR:H1111L5555:16.766:-48.76:full address name is at the end"
1340 // ca. 9 chars : ca. 9 chars : max. 100 max. 100 max. 100 chars -> this sould be max. about 320 chars long
1341 if (slr->town->common.postal == NULL)
1342 {
1343 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);
1344 }
1345 else
1346 {
1347 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);
1348 }
1349 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1350
1351 //// dbg(0,"res=%s\n",buffer);
1352
1353 #ifdef HAVE_API_ANDROID
1354 // return results to android as they come in ...
1355 android_return_search_result(jni,buffer);
1356 #endif
1357 count++;
1358
1359 buffer2 = g_strdup_printf("%s", slr->street->name);
1360 //// dbg(0,"b2:%s\n",buffer2);
1361
1362
1363 save_item = sl->item;
1364 save_level = sl->level;
1365 save_last_result_valid = sl->last_result_valid;
1366
1367 #if 1
1368 // put words back to start!!
1369 tmp = phrases;
1370 while (tmp)
1371 {
1372 if (offline_search_break_searching == 1)
1373 {
1374 break;
1375 }
1376
1377 //// dbg(0,"s0=%s\n",tmp->data);
1378 if (tmp != exclude1 && tmp != exclude2 && tmp != exclude3)
1379 {
1380 //// dbg(0,"s=%s\n",tmp->data);
1381
1382 attr2.type = attr_house_number;
1383 attr2.u.str = tmp->data;
1384 search_list_search(sl, &attr2, partial);
1385 result_list = search_address_housenumber_real(result_list, sl, buffer2, phrases, exclude1, exclude2, exclude3, partial, jni);
1386 }
1387 tmp = g_list_next(tmp);
1388 }
1389 #endif
1390
1391 // restore again
1392 sl->item = save_item;
1393 sl->level = save_level;
1394 sl->last_result_valid = save_last_result_valid;
1395
1396 }
1397
1398 if (buffer2)
1399 {
1400 g_free(buffer2);
1401 }
1402
1403 if (buffer)
1404 {
1405 g_free(buffer);
1406 }
1407 }
1408
1409 //// dbg(0,"return 2\n");
1410 return result_list;
1411 }
1412
1413 static GList *
1414 search_address__town(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude1, GList *exclude2, int partial, struct jni_object *jni)
1415 {
1416 //// dbg(0,"enter\n");
1417 struct search_list_result *slr;
1418 GList *tmp = phrases;
1419 int count = 0;
1420 struct coord_geo g;
1421 struct coord c;
1422 struct attr attr;
1423 struct attr attrx;
1424 // struct search_list *sl2=search_list_new(sl->ms);
1425 struct item *save_item;
1426 int save_level;
1427 int save_last_result_valid;
1428 // int first=1;
1429
1430 while ((slr = search_list_get_result(sl)))
1431 {
1432 char *buffer;
1433
1434 if (offline_search_break_searching == 1)
1435 {
1436 break;
1437 }
1438
1439 // coords of result
1440 c.x = slr->town->common.c->x;
1441 c.y = slr->town->common.c->y;
1442 transform_to_geo(slr->town->common.c->pro, &c, &g);
1443
1444 // TWN -> town
1445 if (slr->town->common.postal == NULL)
1446 {
1447 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);
1448 }
1449 else
1450 {
1451 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);
1452 }
1453
1454 //// dbg(0,"**res=%s\n",buffer);
1455
1456 // deactivated now * result_list=g_list_prepend(result_list,g_strdup(buffer));
1457 #ifdef HAVE_API_ANDROID
1458 // return results to android as they come in ...
1459 android_return_search_result(jni,buffer);
1460 #endif
1461
1462 count++;
1463 if (buffer)
1464 {
1465 g_free(buffer);
1466 }
1467
1468 save_item = sl->item;
1469 save_level = sl->level;
1470 save_last_result_valid = sl->last_result_valid;
1471
1472 // put words back to start!!
1473 tmp = phrases;
1474
1475 while (tmp)
1476 {
1477 if (offline_search_break_searching == 1)
1478 {
1479 break;
1480 }
1481
1482 if (tmp != exclude1 && tmp != exclude2)
1483 {
1484 //// dbg(0,"s=%s\n",tmp->data);
1485 attr.type = attr_street_name;
1486 attr.u.str = tmp->data;
1487 search_list_search(sl, &attr, partial);
1488 result_list = search_address__street(result_list, sl, phrases, exclude1, exclude2, tmp, partial, jni);
1489 }
1490 tmp = g_list_next(tmp);
1491 }
1492
1493 // restore again
1494 sl->item = save_item;
1495 sl->level = save_level;
1496 sl->last_result_valid = save_last_result_valid;
1497 }
1498
1499 //// dbg(0,"return 2\n");
1500 return result_list;
1501 }
1502
1503 static GList *
1504 search_address__country(GList *result_list, struct search_list *sl, GList *phrases, GList *exclude, int partial, struct jni_object *jni)
1505 {
1506 GList *tmp = phrases;
1507 int count = 0;
1508 struct attr attr;
1509 struct search_list_result *slr;
1510 //// dbg(0,"enter\n");
1511
1512 while ((slr = search_list_get_result(sl)))
1513 {
1514 //// dbg(0,"1 slr=%p\n",slr->country);
1515 //// dbg(0,"2 slr=%s\n",slr->country->name);
1516 //// dbg(0,"3 slr=%s\n",slr->country->iso2);
1517 count++;
1518 }
1519 //// dbg(0,"count %d\n",count);
1520 if (!count)
1521 {
1522 //// dbg(0,"return 1");
1523 return result_list;
1524 }
1525
1526 while (tmp)
1527 {
1528 if (tmp != exclude)
1529 {
1530 //// dbg(0,"Is=%s\n",tmp->data);
1531 attr.type = attr_town_or_district_name;
1532 attr.u.str = tmp->data;
1533 search_list_search(sl, &attr, partial);
1534 result_list = search_address__town(result_list, sl, phrases, exclude, tmp, partial, jni);
1535 }
1536 //else
1537 //{
1538 //// dbg(0,"Xs=%s\n",tmp->data);
1539 //}
1540 tmp = g_list_next(tmp);
1541 }
1542 //// dbg(0,"return 2");
1543 return result_list;
1544 }
1545
1546 struct country2
1547 {
1548 int id;
1549 char *car;
1550 char *iso2;
1551 char *iso3;
1552 char *name;
1553 };
1554
1555 static struct country2
1556 all_country_list[] =
1557 { { 20, "AND", "AD", "AND", /* 020 */"Andorra" }, { 784, "UAE", "AE", "ARE", /* 784 */
1558 "United Arab Emirates" }, { 4, "AFG", "AF", "AFG", /* 004 */"Afghanistan" }, { 28, "AG", "AG", "ATG", /* 028 */"Antigua and Barbuda" }, { 660, NULL, "AI", "AIA", /* 660 */"Anguilla" }, { 8, "AL", "AL", "ALB", /* 008 */"Albania" }, { 51, "ARM", "AM", "ARM", /* 051 */"Armenia" }, { 530, "NA", "AN", "ANT", /* 530 */
1559 "Netherlands Antilles" }, { 24, "ANG", "AO", "AGO", /* 024 */"Angola" }, { 10, NULL, "AQ", "ATA", /* 010 */"Antarctica" }, { 32, "RA", "AR", "ARG", /* 032 */"Argentina" }, { 16, NULL, "AS", "ASM", /* 016 */"American Samoa" }, { 40, "A", "AT", "AUT", /* 040 */"Austria" }, { 36, "AUS", "AU", "AUS", /* 036 */"Australia" }, { 533, "ARU", "AW", "ABW", /* 533 */"Aruba" }, { 248, "AX", "AX", "ALA", /* 248 */"Aland Islands" }, { 31, "AZ", "AZ", "AZE", /* 031 */"Azerbaijan" }, { 70, "BiH", "BA", "BIH", /* 070 */
1560 "Bosnia and Herzegovina" }, { 52, "BDS", "BB", "BRB", /* 052 */"Barbados" }, { 50, "BD", "BD", "BGD", /* 050 */"Bangladesh" }, { 56, "B", "BE", "BEL", /* 056 */"Belgium" }, { 854, "BF", "BF", "BFA", /* 854 */"Burkina Faso" }, { 100, "BG", "BG", "BGR", /* 100 */"Bulgaria" }, { 48, "BRN", "BH", "BHR", /* 048 */"Bahrain" }, { 108, "RU", "BI", "BDI", /* 108 */"Burundi" }, { 204, "BJ", "BJ", "BEN", /* 204 */"Benin" }, { 652, NULL, "BL", "BLM", /* 652 */"Saint Barthelemy" }, { 60, NULL, "BM", "BMU", /* 060 */"Bermuda" }, { 96, "BRU", "BN", "BRN", /* 096 */"Brunei Darussalam" }, { 68, "BOL", "BO", "BOL", /* 068 */"Bolivia" }, { 76, "BR", "BR", "BRA", /* 076 */"Brazil" }, { 44, "BS", "BS", "BHS", /* 044 */"Bahamas" }, { 64, "BHT", "BT", "BTN", /* 064 */"Bhutan" }, { 74, NULL, "BV", "BVT", /* 074 */"Bouvet Island" }, { 72, "RB", "BW", "BWA", /* 072 */"Botswana" }, { 112, "BY", "BY", "BLR", /* 112 */"Belarus" }, { 84, "BZ", "BZ", "BLZ", /* 084 */"Belize" }, { 124, "CDN", "CA", "CAN", /* 124 */"Canada" }, { 166, NULL, "CC", "CCK", /* 166 */
1561 "Cocos (Keeling) Islands" }, { 180, "CGO", "CD", "COD", /* 180 */
1562 "Congo, Democratic Republic of the" }, { 140, "RCA", "CF", "CAF", /* 140 */
1563 "Central African Republic" }, { 178, NULL, "CG", "COG", /* 178 */"Congo" }, { 756, "CH", "CH", "CHE", /* 756 */"Switzerland" }, { 384, "CI", "CI", "CIV", /* 384 */"Cote d'Ivoire" }, { 184, NULL, "CK", "COK", /* 184 */"Cook Islands" }, { 152, "RCH", "CL", "CHL", /* 152 */"Chile" }, { 120, "CAM", "CM", "CMR", /* 120 */"Cameroon" }, { 156, "RC", "CN", "CHN", /* 156 */"China" }, { 170, "CO", "CO", "COL", /* 170 */"Colombia" }, { 188, "CR", "CR", "CRI", /* 188 */"Costa Rica" }, { 192, "C", "CU", "CUB", /* 192 */"Cuba" }, { 132, "CV", "CV", "CPV", /* 132 */"Cape Verde" }, { 162, NULL, "CX", "CXR", /* 162 */"Christmas Island" }, { 196, "CY", "CY", "CYP", /* 196 */"Cyprus" }, { 203, "CZ", "CZ", "CZE", /* 203 */"Czech Republic" }, { 276, "D", "DE", "DEU", /* 276 */"Germany" }, { 262, "DJI", "DJ", "DJI", /* 262 */"Djibouti" }, { 208, "DK", "DK", "DNK", /* 208 */"Denmark" }, { 212, "WD", "DM", "DMA", /* 212 */"Dominica" }, { 214, "DOM", "DO", "DOM", /* 214 */
1564 "Dominican Republic" }, { 12, "DZ", "DZ", "DZA", /* 012 */"Algeria" }, { 218, "EC", "EC", "ECU", /* 218 */"Ecuador" }, { 233, "EST", "EE", "EST", /* 233 */"Estonia" }, { 818, "ET", "EG", "EGY", /* 818 */"Egypt" }, { 732, "WSA", "EH", "ESH", /* 732 */"Western Sahara" }, { 232, "ER", "ER", "ERI", /* 232 */"Eritrea" }, { 724, "E", "ES", "ESP", /* 724 */"Spain" }, { 231, "ETH", "ET", "ETH", /* 231 */"Ethiopia" }, { 246, "FIN", "FI", "FIN", /* 246 */"Finland" }, { 242, "FJI", "FJ", "FJI", /* 242 */"Fiji" }, { 238, NULL, "FK", "FLK", /* 238 */
1565 "Falkland Islands (Malvinas)" }, { 583, "FSM", "FM", "FSM", /* 583 */
1566 "Micronesia, Federated States of" }, { 234, "FO", "FO", "FRO", /* 234 */"Faroe Islands" }, { 250, "F", "FR", "FRA", /* 250 */"France" }, { 266, "G", "GA", "GAB", /* 266 */"Gabon" }, { 826, "GB", "GB", "GBR", /* 826 */"United Kingdom" }, { 308, "WG", "GD", "GRD", /* 308 */"Grenada" }, { 268, "GE", "GE", "GEO", /* 268 */"Georgia" }, { 254, NULL, "GF", "GUF", /* 254 */"French Guiana" }, { 831, NULL, "GG", "GGY", /* 831 */"Guernsey" }, { 288, "GH", "GH", "GHA", /* 288 */"Ghana" }, { 292, "GBZ", "GI", "GIB", /* 292 */"Gibraltar" }, { 304, "KN", "GL", "GRL", /* 304 */"Greenland" }, { 270, "WAG", "GM", "GMB", /* 270 */"Gambia" }, { 324, "RG", "GN", "GIN", /* 324 */"Guinea" }, { 312, NULL, "GP", "GLP", /* 312 */"Guadeloupe" }, { 226, "GQ", "GQ", "GNQ", /* 226 */"Equatorial Guinea" }, { 300, "GR", "GR", "GRC", /* 300 */"Greece" }, { 239, NULL, "GS", "SGS", /* 239 */
1567 "South Georgia and the South Sandwich Islands" }, { 320, "GCA", "GT", "GTM", /* 320 */"Guatemala" }, { 316, NULL, "GU", "GUM", /* 316 */"Guam" }, { 624, "GUB", "GW", "GNB", /* 624 */"Guinea-Bissau" }, { 328, "GUY", "GY", "GUY", /* 328 */"Guyana" }, { 344, "HK", "HK", "HKG", /* 344 */"Hong Kong" }, { 334, NULL, "HM", "HMD", /* 334 */
1568 "Heard Island and McDonald Islands" }, { 340, "HN", "HN", "HND", /* 340 */"Honduras" }, { 191, "HR", "HR", "HRV", /* 191 */"Croatia" }, { 332, "RH", "HT", "HTI", /* 332 */"Haiti" }, { 348, "H", "HU", "HUN", /* 348 */"Hungary" }, { 360, "RI", "ID", "IDN", /* 360 */"Indonesia" }, { 372, "IRL", "IE", "IRL", /* 372 */"Ireland" }, { 376, "IL", "IL", "ISR", /* 376 */"Israel" }, { 833, NULL, "IM", "IMN", /* 833 */"Isle of Man" }, { 356, "IND", "IN", "IND", /* 356 */"India" }, { 86, NULL, "IO", "IOT", /* 086 */
1569 "British Indian Ocean Territory" }, { 368, "IRQ", "IQ", "IRQ", /* 368 */"Iraq" }, { 364, "IR", "IR", "IRN", /* 364 */
1570 "Iran, Islamic Republic of" }, { 352, "IS", "IS", "ISL", /* 352 */"Iceland" }, { 380, "I", "IT", "ITA", /* 380 */"Italy" }, { 832, NULL, "JE", "JEY", /* 832 */"Jersey" }, { 388, "JA", "JM", "JAM", /* 388 */"Jamaica" }, { 400, "JOR", "JO", "JOR", /* 400 */"Jordan" }, { 392, "J", "JP", "JPN", /* 392 */"Japan" }, { 404, "EAK", "KE", "KEN", /* 404 */"Kenya" }, { 417, "KS", "KG", "KGZ", /* 417 */"Kyrgyzstan" }, { 116, "K", "KH", "KHM", /* 116 */"Cambodia" }, { 296, "KIR", "KI", "KIR", /* 296 */"Kiribati" }, { 174, "COM", "KM", "COM", /* 174 */"Comoros" }, { 659, "KAN", "KN", "KNA", /* 659 */
1571 "Saint Kitts and Nevis" }, { 408, "KP", "KP", "PRK", /* 408 */
1572 "Korea, Democratic People's Republic of" }, { 410, "ROK", "KR", "KOR", /* 410 */
1573 "Korea, Republic of" }, { 414, "KWT", "KW", "KWT", /* 414 */"Kuwait" }, { 136, NULL, "KY", "CYM", /* 136 */"Cayman Islands" }, { 398, "KZ", "KZ", "KAZ", /* 398 */"Kazakhstan" }, { 418, "LAO", "LA", "LAO", /* 418 */
1574 "Lao People's Democratic Republic" }, { 422, "RL", "LB", "LBN", /* 422 */"Lebanon" }, { 662, "WL", "LC", "LCA", /* 662 */"Saint Lucia" }, { 438, "FL", "LI", "LIE", /* 438 */"Liechtenstein" }, { 144, "CL", "LK", "LKA", /* 144 */"Sri Lanka" }, { 430, "LB", "LR", "LBR", /* 430 */"Liberia" }, { 426, "LS", "LS", "LSO", /* 426 */"Lesotho" }, { 440, "LT", "LT", "LTU", /* 440 */"Lithuania" }, { 442, "L", "LU", "LUX", /* 442 */"Luxembourg" }, { 428, "LV", "LV", "LVA", /* 428 */"Latvia" }, { 434, "LAR", "LY", "LBY", /* 434 */
1575 "Libyan Arab Jamahiriya" }, { 504, "MA", "MA", "MAR", /* 504 */"Morocco" }, { 492, "MC", "MC", "MCO", /* 492 */"Monaco" }, { 498, "MD", "MD", "MDA", /* 498 */
1576 "Moldova, Republic of" }, { 499, "MNE", "ME", "MNE", /* 499 */"Montenegro" }, { 663, NULL, "MF", "MAF", /* 663 */
1577 "Saint Martin (French part)" }, { 450, "RM", "MG", "MDG", /* 450 */"Madagascar" }, { 584, "MH", "MH", "MHL", /* 584 */"Marshall Islands" }, { 807, "MK", "MK", "MKD", /* 807 */
1578 "Macedonia, the former Yugoslav Republic of" }, { 466, "RMM", "ML", "MLI", /* 466 */"Mali" }, { 104, "MYA", "MM", "MMR", /* 104 */"Myanmar" }, { 496, "MGL", "MN", "MNG", /* 496 */"Mongolia" }, { 446, NULL, "MO", "MAC", /* 446 */"Macao" }, { 580, NULL, "MP", "MNP", /* 580 */
1579 "Northern Mariana Islands" }, { 474, NULL, "MQ", "MTQ", /* 474 */"Martinique" }, { 478, "RIM", "MR", "MRT", /* 478 */"Mauritania" }, { 500, NULL, "MS", "MSR", /* 500 */"Montserrat" }, { 470, "M", "MT", "MLT", /* 470 */"Malta" }, { 480, "MS", "MU", "MUS", /* 480 */"Mauritius" }, { 462, "MV", "MV", "MDV", /* 462 */"Maldives" }, { 454, "MW", "MW", "MWI", /* 454 */"Malawi" }, { 484, "MEX", "MX", "MEX", /* 484 */"Mexico" }, { 458, "MAL", "MY", "MYS", /* 458 */"Malaysia" }, { 508, "MOC", "MZ", "MOZ", /* 508 */"Mozambique" }, { 516, "NAM", "NA", "NAM", /* 516 */"Namibia" }, { 540, "NCL", "NC", "NCL", /* 540 */"New Caledonia" }, { 562, "RN", "NE", "NER", /* 562 */"Niger" }, { 574, NULL, "NF", "NFK", /* 574 */"Norfolk Island" }, { 566, "NGR", "NG", "NGA", /* 566 */"Nigeria" }, { 558, "NIC", "NI", "NIC", /* 558 */"Nicaragua" }, { 528, "NL", "NL", "NLD", /* 528 */"Netherlands" }, { 578, "N", "NO", "NOR", /* 578 */"Norway" }, { 524, "NEP", "NP", "NPL", /* 524 */"Nepal" }, { 520, "NAU", "NR", "NRU", /* 520 */"Nauru" }, { 570, NULL, "NU", "NIU", /* 570 */"Niue" }, { 554, "NZ", "NZ", "NZL", /* 554 */"New Zealand" }, { 512, "OM", "OM", "OMN", /* 512 */"Oman" }, { 591, "PA", "PA", "PAN", /* 591 */"Panama" }, { 604, "PE", "PE", "PER", /* 604 */"Peru" }, { 258, NULL, "PF", "PYF", /* 258 */"French Polynesia" }, { 598, "PNG", "PG", "PNG", /* 598 */"Papua New Guinea" }, { 608, "RP", "PH", "PHL", /* 608 */"Philippines" }, { 586, "PK", "PK", "PAK", /* 586 */"Pakistan" }, { 616, "PL", "PL", "POL", /* 616 */"Poland" }, { 666, NULL, "PM", "SPM", /* 666 */
1580 "Saint Pierre and Miquelon" }, { 612, NULL, "PN", "PCN", /* 612 */"Pitcairn" }, { 630, "PRI", "PR", "PRI", /* 630 */"Puerto Rico" }, { 275, "AUT", "PS", "PSE", /* 275 */
1581 "Palestinian Territory, Occupied" }, { 620, "P", "PT", "PRT", /* 620 */"Portugal" }, { 585, "PAL", "PW", "PLW", /* 585 */"Palau" }, { 600, "PY", "PY", "PRY", /* 600 */"Paraguay" }, { 634, "Q", "QA", "QAT", /* 634 */"Qatar" }, { 638, NULL, "RE", "REU", /* 638 */"Reunion" }, { 642, "RO", "RO", "ROU", /* 642 */"Romania" }, { 688, "SRB", "RS", "SRB", /* 688 */"Serbia" }, { 643, "RUS", "RU", "RUS", /* 643 */
1582 "Russian Federation" }, { 646, "RWA", "RW", "RWA", /* 646 */"Rwanda" }, { 682, "KSA", "SA", "SAU", /* 682 */"Saudi Arabia" }, { 90, "SOL", "SB", "SLB", /* 090 */"Solomon Islands" }, { 690, "SY", "SC", "SYC", /* 690 */"Seychelles" }, { 736, "SUD", "SD", "SDN", /* 736 */"Sudan" }, { 752, "S", "SE", "SWE", /* 752 */"Sweden" }, { 702, "SGP", "SG", "SGP", /* 702 */"Singapore" }, { 654, NULL, "SH", "SHN", /* 654 */"Saint Helena" }, { 705, "SLO", "SI", "SVN", /* 705 */"Slovenia" }, { 744, NULL, "SJ", "SJM", /* 744 */
1583 "Svalbard and Jan Mayen" }, { 703, "SK", "SK", "SVK", /* 703 */"Slovakia" }, { 694, "WAL", "SL", "SLE", /* 694 */"Sierra Leone" }, { 674, "RSM", "SM", "SMR", /* 674 */"San Marino" }, { 686, "SN", "SN", "SEN", /* 686 */"Senegal" }, { 706, "SO", "SO", "SOM", /* 706 */"Somalia" }, { 740, "SME", "SR", "SUR", /* 740 */"Suriname" }, { 678, "STP", "ST", "STP", /* 678 */
1584 "Sao Tome and Principe" }, { 222, "ES", "SV", "SLV", /* 222 */"El Salvador" }, { 760, "SYR", "SY", "SYR", /* 760 */
1585 "Syrian Arab Republic" }, { 748, "SD", "SZ", "SWZ", /* 748 */"Swaziland" }, { 796, NULL, "TC", "TCA", /* 796 */
1586 "Turks and Caicos Islands" }, { 148, "TD", "TD", "TCD", /* 148 */"Chad" }, { 260, "ARK", "TF", "ATF", /* 260 */
1587 "French Southern Territories" }, { 768, "RT", "TG", "TGO", /* 768 */"Togo" }, { 764, "T", "TH", "THA", /* 764 */"Thailand" }, { 762, "TJ", "TJ", "TJK", /* 762 */"Tajikistan" }, { 772, NULL, "TK", "TKL", /* 772 */"Tokelau" }, { 626, "TL", "TL", "TLS", /* 626 */"Timor-Leste" }, { 795, "TM", "TM", "TKM", /* 795 */"Turkmenistan" }, { 788, "TN", "TN", "TUN", /* 788 */"Tunisia" }, { 776, "TON", "TO", "TON", /* 776 */"Tonga" }, { 792, "TR", "TR", "TUR", /* 792 */"Turkey" }, { 780, "TT", "TT", "TTO", /* 780 */
1588 "Trinidad and Tobago" }, { 798, "TUV", "TV", "TUV", /* 798 */"Tuvalu" }, { 158, NULL, "TW", "TWN", /* 158 */
1589 "Taiwan, Province of China" }, { 834, "EAT", "TZ", "TZA", /* 834 */
1590 "Tanzania, United Republic of" }, { 804, "UA", "UA", "UKR", /* 804 */"Ukraine" }, { 800, "EAU", "UG", "UGA", /* 800 */"Uganda" }, { 581, NULL, "UM", "UMI", /* 581 */
1591 "United States Minor Outlying Islands" }, { 840, "USA", "US", "USA", /* 840 */"United States" }, { 858, "ROU", "UY", "URY", /* 858 */"Uruguay" }, { 860, "UZ", "UZ", "UZB", /* 860 */"Uzbekistan" }, { 336, "SCV", "VA", "VAT", /* 336 */
1592 "Holy See (Vatican City State)" }, { 670, "WV", "VC", "VCT", /* 670 */"Saint Vincent and the Grenadines" }, { 862, "YV", "VE", "VEN", /* 862 */"Venezuela" }, { 92, NULL, "VG", "VGB", /* 092 */"Virgin Islands, British" }, { 850, NULL, "VI", "VIR", /* 850 */"Virgin Islands, U.S." }, { 704, "VN", "VN", "VNM", /* 704 */"Viet Nam" }, { 548, "VAN", "VU", "VUT", /* 548 */"Vanuatu" }, { 876, NULL, "WF", "WLF", /* 876 */"Wallis and Futuna" }, { 882, "WS", "WS", "WSM", /* 882 */"Samoa" }, { 887, "YAR", "YE", "YEM", /* 887 */"Yemen" }, { 175, NULL, "YT", "MYT", /* 175 */"Mayotte" }, { 710, "ZA", "ZA", "ZAF", /* 710 */"South Africa" }, { 894, "Z", "ZM", "ZMB", /* 894 */"Zambia" }, { 716, "ZW", "ZW", "ZWE", /* 716 */"Zimbabwe" }, { 999, "*", "*", "*", /* 999 */"Unknown" }, };
1593
1594 // @return =0 strings matched, =1 not matched
1595 static int ascii_cmp_local(char *name, char *match, int partial)
1596 {
1597 char *s1_a;
1598 char *s2_a;
1599
1600 char *s1 = linguistics_casefold(name);
1601 char *s2 = linguistics_casefold(match);
1602
1603 if (s1)
1604 {
1605 s1_a = linguistics_remove_all_specials(s1);
1606 if (s1_a)
1607 {
1608 g_free(s1);
1609 s1 = s1_a;
1610 }
1611 s1_a = linguistics_expand_special(s1, 1);
1612 if (s1_a)
1613 {
1614 g_free(s1);
1615 s1 = s1_a;
1616 }
1617 }
1618
1619 if (s2)
1620 {
1621 s2_a = linguistics_remove_all_specials(s2);
1622 if (s2_a)
1623 {
1624 g_free(s2);
1625 s2 = s2_a;
1626 }
1627 s2_a = linguistics_expand_special(s2, 1);
1628 if (s2_a)
1629 {
1630 g_free(s2);
1631 s2 = s2_a;
1632 }
1633 }
1634
1635 int ret = linguistics_compare(s1, s2, partial);
1636
1637 if (s1)
1638 {
1639 g_free(s1);
1640 }
1641
1642 if (s2)
1643 {
1644 g_free(s2);
1645 }
1646
1647 return ret;
1648 }
1649
1650 // @return =0 strings matched, =1 not matched
1651 static int ascii_cmp_local_faster(char *name, char *match, int partial)
1652 {
1653 char *s1_a;
1654 char *s1 = name;
1655 int ret;
1656
1657 s1_a = linguistics_fold_and_prepare_complete(s1, 0);
1658
1659 if (!s1_a)
1660 {
1661 return 1;
1662 }
1663
1664 // dbg(0,"s1=%s match=%s\n", s1_a, match);
1665
1666 if (strlen(s1_a) == 0)
1667 {
1668 // only special chars in string, return "no match"
1669 return 1;
1670 }
1671
1672
1673 // --- old ---
1674 //ret = linguistics_compare(s1, match, partial);
1675 // --- old ---
1676
1677 if (partial == 1)
1678 {
1679 ret = strncmp(s1_a, match, strlen(match));
1680 }
1681 else
1682 {
1683 if (strlen(s1_a) == strlen(match))
1684 {
1685 ret = strncmp(s1_a, match, strlen(match));
1686 }
1687 else
1688 {
1689 ret = 1;
1690 }
1691 }
1692
1693
1694 if (s1_a)
1695 {
1696 g_free(s1_a);
1697 }
1698
1699 return ret;
1700 }
1701
1702 struct navit *global_navit;
1703
1704 void search_full_world(char *addr, int partial, int search_order, struct jni_object *jni, struct coord_geo *search_center, int search_radius)
1705 {
1706 struct item *item;
1707 struct map_rect *mr = NULL;
1708 struct mapset *ms;
1709 struct mapset_handle *msh;
1710 struct map* map = NULL;
1711 struct attr map_name_attr;
1712 struct attr attr;
1713
1714 char *str = search_fix_spaces(addr);
1715 GList *phrases = search_split_phrases(str);
1716 GList *phrases_first;
1717 phrases_first = phrases;
1718
1719 ms = global_navit->mapsets->data;
1720 msh = mapset_open(ms);
1721
1722 struct pcoord center99;
1723 int search_radius_this = 0;
1724 // dbg(0, "in lat=%f,lng=%f\n", search_center->lat, search_center->lng);
1725 if ((search_center->lat == 0) && (search_center->lng == 0))
1726 {
1727 center99.x = 0;
1728 center99.y = 0;
1729 search_radius_this = 21000000;
1730 }
1731 else
1732 {
1733 struct coord c99;
1734 transform_from_geo(projection_mg, search_center, &c99);
1735 center99.x = c99.x;
1736 center99.y = c99.y;
1737 search_radius_this = search_radius;
1738 }
1739 // dbg(0, "out x=%d,y=%d,r=%d\n", center99.x, center99.y, search_radius_this);
1740
1741 struct map_selection *sel = map_selection_rect_new(&center99, search_radius_this, search_order);
1742 sel->range.min = type_town_label;
1743 sel->range.max = type_area;
1744
1745 while (msh && (map = mapset_next(msh, 0)))
1746 {
1747 if (offline_search_break_searching == 1)
1748 {
1749 break;
1750 }
1751
1752 if (map_get_attr(map, attr_name, &map_name_attr, NULL))
1753 {
1754 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
1755 {
1756 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/navitmap", map_name_attr.u.str, 38) == 0)
1757 {
1758 // its an sdcard map
1759 //// dbg(0,"map name=%s",map_name_attr.u.str);
1760 // mr=map_rect_new(map, NULL);
1761 mr = map_rect_new(map, sel);
1762 if (mr)
1763 {
1764 char *streetname_last = NULL;
1765
1766 while ((item = map_rect_get_item(mr)))
1767 {
1768
1769 if (offline_search_break_searching == 1)
1770 {
1771 break;
1772 }
1773
1774 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
1775 g_mem_profile();
1776 #endif
1777
1778 if ((item_is_town(*item)) || (item_is_district(*item)))
1779 {
1780 struct search_list_town *p = NULL;
1781
1782 if (item_attr_get(item, attr_town_name, &attr))
1783 {
1784 p = search_list_town_new(item);
1785 char *buffer = NULL;
1786 // coords of result
1787 struct coord_geo g;
1788 struct coord c;
1789 c.x = p->common.c->x;
1790 c.y = p->common.c->y;
1791 int calc_geo = 0;
1792
1793 // // dbg(0,"town name=%s\n", attr.u.str);
1794
1795 phrases = phrases_first;
1796 while (phrases)
1797 {
1798
1799 if (offline_search_break_searching == 1)
1800 {
1801 break;
1802 }
1803
1804 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1805 {
1806 // // dbg(0,"matched town name=%s want=%s\n", attr.u.str, phrases->data);
1807 if (calc_geo == 0)
1808 {
1809 transform_to_geo(p->common.c->pro, &c, &g);
1810 // TWN -> town
1811 calc_geo = 1;
1812 }
1813 if (p->common.postal == NULL)
1814 {
1815 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);
1816 }
1817 else
1818 {
1819 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);
1820 }
1821 #ifdef HAVE_API_ANDROID
1822 // return results to android as they come in ...
1823 android_return_search_result(jni,buffer);
1824 #endif
1825 }
1826 phrases = g_list_next(phrases);
1827
1828 }
1829
1830 if (buffer)
1831 {
1832 g_free(buffer);
1833 }
1834 search_list_town_destroy(p);
1835 }
1836
1837 if (item_attr_get(item, attr_town_name_match, &attr))
1838 {
1839 p = search_list_town_new(item);
1840 char *buffer = NULL;
1841 // coords of result
1842 struct coord_geo g;
1843 struct coord c;
1844 c.x = p->common.c->x;
1845 c.y = p->common.c->y;
1846 int calc_geo = 0;
1847
1848 // // dbg(0,"town name=%s\n", attr.u.str);
1849
1850 phrases = phrases_first;
1851 while (phrases)
1852 {
1853 if (offline_search_break_searching == 1)
1854 {
1855 break;
1856 }
1857
1858 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1859 {
1860 // // dbg(0,"matched town name=%s want=%s\n", attr.u.str, phrases->data);
1861 if (calc_geo == 0)
1862 {
1863 transform_to_geo(p->common.c->pro, &c, &g);
1864 // TWN -> town
1865 calc_geo = 1;
1866 }
1867 if (p->common.postal == NULL)
1868 {
1869 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);
1870 }
1871 else
1872 {
1873 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);
1874 }
1875 #ifdef HAVE_API_ANDROID
1876 // return results to android as they come in ...
1877 android_return_search_result(jni,buffer);
1878 #endif
1879 }
1880 phrases = g_list_next(phrases);
1881
1882 }
1883
1884 if (buffer)
1885 {
1886 g_free(buffer);
1887 }
1888 search_list_town_destroy(p);
1889 }
1890 }
1891 else if (item_is_street(*item))
1892 {
1893
1894 struct search_list_street *p = NULL;
1895
1896 if (item_attr_get(item, attr_label, &attr))
1897 {
1898 // // dbg(0,"street1=%s\n",map_convert_string(item->map, attr.u.str));
1899 if ((streetname_last == NULL) || (strcmp(streetname_last, attr.u.str) != 0))
1900 {
1901 // // dbg(0,"street2=%s\n",map_convert_string(item->map, attr.u.str));
1902 streetname_last = g_strdup_printf("%s", attr.u.str);
1903
1904 p = search_list_street_new(item);
1905 char *buffer = NULL;
1906 // coords of result
1907 struct coord_geo g;
1908 struct coord c;
1909 c.x = p->common.c->x;
1910 c.y = p->common.c->y;
1911 int calc_geo = 0;
1912
1913 phrases = phrases_first;
1914 while (phrases)
1915 {
1916 if (offline_search_break_searching == 1)
1917 {
1918 break;
1919 }
1920
1921 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1922 {
1923 if (calc_geo == 0)
1924 {
1925 transform_to_geo(p->common.c->pro, &c, &g);
1926 calc_geo = 1;
1927 }
1928 if (p->common.postal == NULL)
1929 {
1930 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);
1931 }
1932 else
1933 {
1934 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);
1935 }
1936 //// dbg(0,"street3=%s\n",buffer);
1937 #ifdef HAVE_API_ANDROID
1938 // return results to android as they come in ...
1939 android_return_search_result(jni,buffer);
1940 #endif
1941 }
1942 phrases = g_list_next(phrases);
1943 }
1944 if (buffer)
1945 {
1946 g_free(buffer);
1947 }
1948 search_list_street_destroy(p);
1949 }
1950 }
1951
1952 if (item_attr_get(item, attr_street_name_match, &attr))
1953 {
1954 //// dbg(0,"street systematic=%s\n",map_convert_string(item->map, attr.u.str));
1955
1956 p = search_list_street_new(item);
1957 char *buffer = NULL;
1958 // coords of result
1959 struct coord_geo g;
1960 struct coord c;
1961 c.x = p->common.c->x;
1962 c.y = p->common.c->y;
1963 int calc_geo = 0;
1964
1965 phrases = phrases_first;
1966 while (phrases)
1967 {
1968 if (offline_search_break_searching == 1)
1969 {
1970 break;
1971 }
1972
1973 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
1974 {
1975 if (calc_geo == 0)
1976 {
1977 transform_to_geo(p->common.c->pro, &c, &g);
1978 calc_geo = 1;
1979 }
1980 if (p->common.postal == NULL)
1981 {
1982 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);
1983 }
1984 else
1985 {
1986 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);
1987 }
1988 #ifdef HAVE_API_ANDROID
1989 // return results to android as they come in ...
1990 android_return_search_result(jni,buffer);
1991 #endif
1992 }
1993 phrases = g_list_next(phrases);
1994 }
1995 if (buffer)
1996 {
1997 g_free(buffer);
1998 }
1999 search_list_street_destroy(p);
2000
2001 }
2002
2003 if (item_attr_get(item, attr_street_name_systematic, &attr))
2004 {
2005 //// dbg(0,"street systematic=%s\n",map_convert_string(item->map, attr.u.str));
2006
2007 p = search_list_street_new(item);
2008 char *buffer = NULL;
2009 // coords of result
2010 struct coord_geo g;
2011 struct coord c;
2012 c.x = p->common.c->x;
2013 c.y = p->common.c->y;
2014 int calc_geo = 0;
2015
2016 phrases = phrases_first;
2017 while (phrases)
2018 {
2019 if (offline_search_break_searching == 1)
2020 {
2021 break;
2022 }
2023
2024 if (!ascii_cmp_local(attr.u.str, phrases->data, partial))
2025 {
2026 if (calc_geo == 0)
2027 {
2028 transform_to_geo(p->common.c->pro, &c, &g);
2029 calc_geo = 1;
2030 }
2031 if (p->common.postal == NULL)
2032 {
2033 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);
2034 }
2035 else
2036 {
2037 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);
2038 }
2039 #ifdef HAVE_API_ANDROID
2040 // return results to android as they come in ...
2041 android_return_search_result(jni,buffer);
2042 #endif
2043 }
2044 phrases = g_list_next(phrases);
2045 }
2046 if (buffer)
2047 {
2048 g_free(buffer);
2049 }
2050 search_list_street_destroy(p);
2051
2052 }
2053 }
2054 }
2055 g_free(streetname_last);
2056 map_rect_destroy(mr);
2057 }
2058 }
2059 }
2060 }
2061 }
2062
2063 map_selection_destroy(sel);
2064
2065 if (phrases)
2066 {
2067 g_list_free(phrases);
2068 }
2069 g_free(str);
2070
2071 mapset_close(msh);
2072
2073 #ifdef DEBUG_GLIB_MEM_FUNCTIONS
2074 g_mem_profile();
2075 #endif
2076 }
2077
2078 GList *
2079 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)
2080 {
2081 char *str = search_fix_spaces(addr);
2082 GList *tmp, *phrases = search_split_phrases(str);
2083 GList *phrases_first;
2084 GList *ret = NULL;
2085 struct search_list *sl;
2086 struct attr attr;
2087 attr.type = attr_country_all;
2088 tmp = phrases;
2089 phrases_first = phrases;
2090 sl = search_list_new(ms);
2091
2092 // dbg(0, "-- START --\n");
2093
2094 // normal search stuff -------- START ----------
2095 if (search_country_flags == 1)
2096 {
2097 // dbg(0, "-- country default start --\n");
2098 //while (phrases)
2099 //{
2100 // // dbg(0,"s=%s\n",phrases->data);
2101 // set default country
2102 search_list_search(sl, country_default(), 0);
2103 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2104 // phrases=g_list_next(phrases);
2105 //}
2106 // dbg(0, "-- country default end --\n");
2107 }
2108 else if (search_country_flags == 2)
2109 {
2110 // dbg(0, "-- country sel:%s start --\n", search_country_string);
2111 // set a country
2112 struct attr country;
2113 country.type = attr_country_iso2;
2114 country.u.str = search_country_string;
2115 //while (phrases)
2116 //{
2117 // // dbg(0,"s=%s\n",phrases->data);
2118 search_list_search(sl, &country, 0);
2119 // set a country
2120 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2121 //phrases=g_list_next(phrases);
2122 //}
2123 // dbg(0, "-- country sel:%s end --\n", search_country_string);
2124 }
2125 else // flags==3
2126 {
2127 // dbg(0, "-- country all start --\n");
2128 // search all countries!! could take a really long time!!
2129 struct attr country;
2130 int j2 = sizeof(all_country_list) / sizeof(all_country_list[0]);
2131 int j1;
2132 for (j1 = 0; j1 < j2; j1++)
2133 {
2134 if (all_country_list[j1].iso2 != NULL)
2135 {
2136 phrases = phrases_first;
2137 //while (phrases)
2138 //{
2139 // // dbg(0,"s country=%s\n",all_country_list[j1].iso2);
2140 // // dbg(0,"s=%s\n",phrases->data);
2141 country.type = attr_country_iso2;
2142 country.u.str = all_country_list[j1].iso2;
2143 search_list_search(sl, &country, 0);
2144 ret = search_address__country(ret, sl, phrases, NULL, partial, jni);
2145 //phrases=g_list_next(phrases);
2146 //}
2147
2148 if (offline_search_break_searching == 1)
2149 {
2150 break;
2151 }
2152 }
2153 }
2154 // dbg(0, "-- country all end --\n");
2155 }
2156 // normal search stuff -------- END ----------
2157
2158 if (phrases_first)
2159 {
2160 g_list_free(phrases_first);
2161 }
2162
2163 // dbg(0, "-- END --\n");
2164
2165 g_free(str);
2166 return ret;
2167 }
2168
2169 // IN_BUF_SIZE2 is the size of the file read buffer.
2170 // IN_BUF_SIZE2 must be >= 1
2171 //#define IN_BUF_SIZE2 (1024*16)
2172 int IN_BUF_SIZE2 = sizeof(struct streets_index_data_block) * 1024;
2173 int t_IN_BUF_SIZE2 = sizeof(struct town_index_data_block) * 1024;
2174 static uint8 s_inbuf[(sizeof(struct streets_index_data_block) * 1024)];
2175 static uint8 t_s_inbuf[(sizeof(struct town_index_data_block) * 1024)];
2176 //static uint8 s_inbuf[IN_BUF_SIZE2];
2177
2178 // OUT_BUF_SIZE2 is the size of the output buffer used during decompression.
2179 // OUT_BUF_SIZE2 must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor
2180 // not only writes, but reads from the output buffer as it decompresses)
2181 //#define OUT_BUF_SIZE2 (TINFL_LZ_DICT_SIZE)
2182 //#define OUT_BUF_SIZE2 (1024*32)
2183 int OUT_BUF_SIZE2 = sizeof(struct streets_index_data_block) * 1024;
2184 int t_OUT_BUF_SIZE2 = sizeof(struct town_index_data_block) * 1024;
2185 static uint8 s_outbuf[(sizeof(struct streets_index_data_block) * 1024)];
2186 static uint8 t_s_outbuf[(sizeof(struct town_index_data_block) * 1024)];
2187 //static uint8 s_outbuf[OUT_BUF_SIZE2];
2188
2189 static long long street_index_size = 0; // this is the offset for town index start
2190 // street index starts at "+sizeof(long long)"
2191
2192 #define my_min(a,b) (((a) < (b)) ? (a) : (b))
2193 #define NUMBER_OF_TOWNS_TO_CACHE 10
2194
2195 static struct town_index_data_block_c *town_lookup_cache = NULL;
2196 static struct town_index_data_block_c *town_lookup_cache_cur = NULL;
2197 static struct town_index_data_block_c *town_lookup_cache_found = NULL;
2198 static int town_lookup_cache_items = 0;
2199 static int town_lookup_cache_cur_item = 0;
2200
2201 void town_index_init_cache()
2202 {
2203 int s = sizeof(struct town_index_data_block_c) * NUMBER_OF_TOWNS_TO_CACHE;
2204 // dbg(0, "cache size=%d\n", s);
2205
2206 town_lookup_cache = g_malloc(s);
2207 town_lookup_cache_cur = town_lookup_cache;
2208 town_lookup_cache_found = NULL;
2209 town_lookup_cache_items = 0;
2210 town_lookup_cache_cur_item = 0;
2211 }
2212
2213 void town_index_insert_cache(struct town_index_data_block* t, char* townname_long)
2214 {
2215 if (town_lookup_cache_items < NUMBER_OF_TOWNS_TO_CACHE)
2216 {
2217 // fill up cache until all slots are filled
2218 town_lookup_cache_cur->town_id = t->town_id;
2219 town_lookup_cache_cur->country_id = t->country_id;
2220 sprintf(town_lookup_cache_cur->town_name, "%s", townname_long);
2221 town_lookup_cache_items++;
2222 }
2223 else
2224 {
2225 // just fill cache and rotate if at end
2226 town_lookup_cache_cur->town_id = t->town_id;
2227 town_lookup_cache_cur->country_id = t->country_id;
2228 sprintf(town_lookup_cache_cur->town_name, "%s", townname_long);
2229 }
2230
2231 if (town_lookup_cache_items == NUMBER_OF_TOWNS_TO_CACHE)
2232 {
2233 town_lookup_cache_cur_item = 0;
2234 town_lookup_cache_cur = town_lookup_cache;
2235 }
2236 else
2237 {
2238 town_lookup_cache_cur_item++;
2239 town_lookup_cache_cur++;
2240 }
2241 }
2242
2243 int town_index_lookup_cache(long long townid)
2244 {
2245 int i;
2246 struct town_index_data_block_c* t;
2247
2248 if (town_lookup_cache_items < 1)
2249 {
2250 return 0;
2251 }
2252
2253 t = town_lookup_cache;
2254 for (i = 0; i < town_lookup_cache_items; i++)
2255 {
2256 if (t->town_id == townid)
2257 {
2258 // set pointer to found datablock
2259 town_lookup_cache_found = t;
2260 return 1;
2261 }
2262 t++;
2263 }
2264
2265 return 0;
2266 }
2267
2268 char* town_index_lookup(struct street_index_head *sih, long long townid)
2269 {
2270 char *townname = NULL;
2271 char *townname2 = NULL;
2272 int found = 0;
2273 int i;
2274 int split = 0;
2275 int split_count = 0;
2276 long long save_town_id;
2277 int save_country_id;
2278
2279 if (townid == 0)
2280 {
2281 return townname;
2282 }
2283
2284 if (town_lookup_cache == NULL)
2285 {
2286 town_index_init_cache();
2287 }
2288
2289 if (town_index_lookup_cache(townid) == 1)
2290 {
2291 townname = g_strdup_printf("%s", town_lookup_cache_found->town_name);
2292 return townname;
2293 }
2294
2295 sih->ti_ib = sih->ti_ib_mem;
2296
2297 // find townid block
2298 found = sih->ti_ibs.count_of_index_blocks - 1; // set to last block
2299 for (i = 0; i < sih->ti_ibs.count_of_index_blocks; i++)
2300 {
2301 //dbg(0, "i=%d %lld %lld\n", i, townid, sih->ti_ib->first_id);
2302
2303 if (townid < sih->ti_ib->first_id)
2304 {
2305 found = i - 1;
2306 break;
2307 }
2308
2309 sih->ti_ib++;
2310 }
2311
2312 if (found != -1)
2313 {
2314 //dbg(0, "found town block num=%d\n", found);
2315
2316 town_index_setpos(sih, found); // move to correct index block
2317
2318 while (town_index_read_data(sih))
2319 {
2320 if (offline_search_break_searching == 1)
2321 {
2322 break;
2323 }
2324
2325 //dbg(0, "id=%lld\n", sih->ti_db_ptr->town_id);
2326
2327 if (sih->ti_db_ptr->town_id == townid)
2328 {
2329 townname = g_strdup_printf("%s", sih->ti_db_ptr->town_name);
2330 //dbg(0,"found town:%s\n", townname);
2331 save_town_id = sih->ti_db_ptr->town_id;
2332 save_country_id = sih->ti_db_ptr->country_id;
2333 split = 1;
2334 split_count = 0;
2335 while ((town_index_read_data(sih))&&(split == 1))
2336 {
2337 split_count++;
2338 if ((split_count + 1) > MAX_TOWNNAME_SPLIT)
2339 {
2340 break;
2341 }
2342
2343 if (sih->ti_db_ptr->town_id == 0)
2344 {
2345 //dbg(0," town-split:%s\n", sih->ti_db_ptr->town_name);
2346 townname2 = g_strdup_printf("%s%s", townname, sih->ti_db_ptr->town_name);
2347 g_free(townname);
2348 townname = townname2;
2349 }
2350 else
2351 {
2352 split = 0;
2353 }
2354 }
2355 break;
2356 }
2357 }
2358 }
2359
2360 if (townname != NULL)
2361 {
2362 sih->ti_db_ptr->town_id = save_town_id; // set town and country to values before we read the "split"-blocks!
2363 sih->ti_db_ptr->country_id = save_country_id;
2364 town_index_insert_cache(sih->ti_db_ptr, townname);
2365 }
2366
2367 //dbg(0, "return\n");
2368
2369 return townname;
2370 }
2371
2372 struct street_index_head* street_index_init(const char* idxfile_name)
2373 {
2374 struct street_index_head *ret=g_new0(struct street_index_head, 1);
2375 long s1;
2376 int b;
2377 char *index_file;
2378
2379 index_file = g_strdup_printf("%s%s", navit_maps_dir, idxfile_name);
2380 ret->sif = fopen(index_file, "rb");
2381 g_free(index_file);
2382
2383 fread(&street_index_size, sizeof(struct streets_index_index_block_start), 1, ret->sif);
2384 //dbg(0, "street_index_size=%lld\n", street_index_size);
2385
2386 b = fread(&ret->si_ibs, sizeof(struct streets_index_index_block_start), 1, ret->sif);
2387 //dbg(0, "ftell=%d\n", ftell(ret->sif));
2388 //dbg(0, "items read=%d\n", b);
2389
2390 //dbg(0, "struct size=%d\n", sizeof(struct streets_index_data_block));
2391
2392 //dbg(0, "index entries=%d\n", ret->si_ibs.count_of_index_blocks);
2393 //dbg(0, "index entry size=%d\n", sizeof(struct streets_index_index_block));
2394 s1 = sizeof(struct streets_index_index_block) * ret->si_ibs.count_of_index_blocks;
2395 //dbg(0, "s1=%ld\n", s1);
2396
2397 ret->si_ib_mem = g_malloc(s1);
2398 ret->si_ib = ret->si_ib_mem;
2399
2400 ret->comp_status = 0;
2401 ret->t_comp_status = 0;
2402
2403 //dbg(0, "ftell=%d\n", ftell(ret->sif));
2404 fread(ret->si_ib_mem, sizeof(struct streets_index_index_block), ret->si_ibs.count_of_index_blocks, ret->sif);
2405 //dbg(0, "ftell=%d\n", ftell(ret->sif));
2406
2407 //dbg(0, "len=%lld\n", ret->si_ib->len);
2408 //dbg(0, "offset=%lld\n", ret->si_ib->offset);
2409
2410 fseek(ret->sif, street_index_size + sizeof(long long), SEEK_SET); // seek to townindex header
2411 fread(&ret->ti_ibs, sizeof(struct town_index_index_block_start), 1, ret->sif);
2412 //dbg(0, "len=%lld\n", ret->ti_ibs.count_of_index_blocks);
2413
2414 //dbg(0, "town index entries=%d\n", ret->ti_ibs.count_of_index_blocks);
2415 //dbg(0, "town index entry size=%d\n", sizeof(struct town_index_index_block));
2416 s1 = sizeof(struct town_index_index_block) * ret->ti_ibs.count_of_index_blocks;
2417 //dbg(0, "s1=%ld\n", s1);
2418
2419 ret->ti_ib_mem = g_malloc(s1);
2420 ret->ti_ib = ret->ti_ib_mem;
2421
2422 //dbg(0, "ftell=%d\n", ftell(ret->sif));
2423 fread(ret->ti_ib_mem, sizeof(struct town_index_index_block), ret->ti_ibs.count_of_index_blocks, ret->sif);
2424 //dbg(0, "ftell=%d\n", ftell(ret->sif));
2425
2426 //dbg(0, "town len=%lld\n", ret->ti_ib->len);
2427 //dbg(0, "town offset=%lld\n", ret->ti_ib->offset);
2428
2429 return ret;
2430 }
2431
2432 void town_index_setpos(struct street_index_head *sih, int town_data_block_num)
2433 {
2434 if (sih->t_comp_status == 1)
2435 {
2436 town_index_close_compr(sih);
2437 }
2438
2439 sih->ti_ib = (sih->ti_ib_mem + town_data_block_num);
2440
2441 town_index_init_compr(sih, sih->ti_ib->len);
2442
2443 //dbg(0, "len=%lld\n", sih->ti_ib->len);
2444 //dbg(0, "fid=%lld\n", sih->ti_ib->first_id);
2445 //dbg(0, "off=%lld\n", sih->ti_ib->offset);
2446
2447 // if (sih->ti_ib->len >= sizeof(struct town_index_data_block))
2448 if (sih->ti_ib->len > 1)
2449 {
2450 //dbg(0, "fpos1=%d\n", ftell(sih->sif));
2451 fseek(sih->sif, sih->ti_ib->offset + sizeof(long long) + street_index_size, SEEK_SET);
2452 //dbg(0, "fpos2=%d\n", ftell(sih->sif));
2453
2454 sih->t_data_count = 0;
2455 // move ptr to first data
2456 sih->ti_db_ptr = t_s_outbuf;
2457 }
2458
2459 }
2460
2461 void street_index_setpos(struct street_index_head *sih, int data_block_num)
2462 {
2463
2464 if (sih->comp_status == 1)
2465 {
2466 street_index_close_compr(sih);
2467 }
2468
2469 sih->si_ib = (sih->si_ib_mem + data_block_num);
2470
2471 //dbg(0, "len=%lld\n", sih->si_ib->len);
2472 //dbg(0, "fl=%c off=%lld\n", sih->si_ib->first_letter, sih->si_ib->offset);
2473
2474 street_index_init_compr(sih, sih->si_ib->len);
2475
2476 //if (sih->si_ib->len >= sizeof(struct streets_index_data_block))
2477 if (sih->si_ib->len > 1) // what is the minimum compressed block size? (about 55 bytes now)
2478 {
2479 //dbg(0, "mem start=%d, cur pos=%d\n", sih->si_ib_mem, sih->si_ib);
2480 //dbg(0, "file offset=%d\n", sih->si_ib->offset);
2481 //dbg(0, "fpos s1=%d\n", ftell(sih->sif));
2482 fseek(sih->sif, sih->si_ib->offset + sizeof(long long), SEEK_SET); // add the "long long" from start of file to offset
2483 //dbg(0, "fpos s2=%d\n", ftell(sih->sif));
2484
2485 sih->data_count = 0;
2486 // move ptr to first data
2487 sih->si_db_ptr = s_outbuf;
2488 }
2489 }
2490
2491 int street_index_read_data(struct street_index_head *sih)
2492 {
2493 // fread(&sih->si_db, sizeof(struct streets_index_data_block), 1, sih->sif);
2494
2495
2496 //if (sih->si_ib->len < sizeof(struct streets_index_data_block))
2497 if (sih->si_ib->len <= 1) // minimum size of compressed block?
2498 {
2499 //dbg(0, "len=%d sof=%d\n", sih->si_ib->len, sizeof(struct streets_index_data_block));
2500 // no data for this letter
2501 return 0;
2502 }
2503
2504 if (sih->data_count == 0)
2505 {
2506 // init
2507 sih->next_out = s_outbuf;
2508 sih->avail_out = OUT_BUF_SIZE2;
2509
2510 // read data
2511 sih->data_count = street_index_decompress_data_block(sih);
2512 //dbg(0, "stat=%d\n", sih->data_count);
2513
2514 if (sih->data_count <= 0)
2515 {
2516 // end of data
2517 return 0;
2518 }
2519
2520 // move ptr to next data
2521 sih->si_db_ptr = s_outbuf;
2522 }
2523 else
2524 {
2525 sih->data_count = sih->data_count - sizeof(struct streets_index_data_block);
2526
2527 if (sih->data_count > 0)
2528 {
2529 sih->si_db_ptr++;
2530 //dbg(0, "dc=%d ptr=%p\n", sih->data_count, sih->si_db_ptr);
2531 }
2532 else
2533 {
2534 // init
2535 sih->next_out = s_outbuf;
2536 sih->avail_out = OUT_BUF_SIZE2;
2537
2538 // read data
2539 sih->data_count = street_index_decompress_data_block(sih);
2540 //dbg(0, "stat2=%d\n", sih->data_count);
2541
2542 if (sih->data_count <= 0)
2543 {
2544 // end of data
2545 return 0;
2546 }
2547
2548 // move ptr to next data
2549 sih->si_db_ptr = s_outbuf;
2550 }
2551 }
2552
2553 //dbg(0, "data=%s, %d, %d, %lld\n", sih->si_db_ptr->street_name, sih->si_db_ptr->lat, sih->si_db_ptr->lon, sih->si_db_ptr->town_id);
2554
2555 return 1;
2556
2557 //if (ftell(sih->sif) > (sih->si_ib->offset + sih->si_ib->len))
2558 //{
2559 // // end of data
2560 // return 0;
2561 //}
2562
2563 // more data found
2564 // return 1;
2565 }
2566
2567 int town_index_read_data(struct street_index_head *sih)
2568 {
2569 // fread(&sih->si_db, sizeof(struct streets_index_data_block), 1, sih->sif);
2570
2571
2572 // if (sih->ti_ib->len < sizeof(struct town_index_data_block))
2573 if (sih->ti_ib->len <= 1)
2574 {
2575 // no data for this block
2576 //fprintf(stderr, "no data for this block\n");
2577 return 0;
2578 }
2579
2580 if (sih->t_data_count == 0)
2581 {
2582 // init
2583 sih->t_next_out = t_s_outbuf;
2584 sih->t_avail_out = t_OUT_BUF_SIZE2;
2585
2586 // read data
2587 sih->t_data_count = town_index_decompress_data_block(sih);
2588 //dbg(0, "stat=%d\n", sih->data_count);
2589
2590 if (sih->t_data_count <= 0)
2591 {
2592 // end of data
2593 //fprintf(stderr, "end of data\n");
2594 return 0;
2595 }
2596
2597 // move ptr to next data
2598 sih->ti_db_ptr = t_s_outbuf;
2599 }
2600 else
2601 {
2602 sih->t_data_count = sih->t_data_count - sizeof(struct town_index_data_block);
2603
2604 if (sih->t_data_count > 0)
2605 {
2606 sih->ti_db_ptr++;
2607 //dbg(0, "dc=%d ptr=%p\n", sih->data_count, sih->si_db_ptr);
2608 }
2609 else
2610 {
2611 // init
2612 sih->t_next_out = t_s_outbuf;
2613 sih->t_avail_out = t_OUT_BUF_SIZE2;
2614
2615 // read data
2616 sih->t_data_count = town_index_decompress_data_block(sih);
2617 //dbg(0, "stat2=%d\n", sih->data_count);
2618
2619 if (sih->t_data_count <= 0)
2620 {
2621 // end of data
2622 //fprintf(stderr, "end of data (2)\n");
2623 return 0;
2624 }
2625
2626 // move ptr to next data
2627 sih->ti_db_ptr = t_s_outbuf;
2628 }
2629 }
2630
2631 //dbg(0, "data=%s, %d, %d, %lld\n", sih->si_db_ptr->street_name, sih->si_db_ptr->lat, sih->si_db_ptr->lon, sih->si_db_ptr->town_id);
2632
2633 return 1;
2634
2635 //if (ftell(sih->sif) > (sih->si_ib->offset + sih->si_ib->len))
2636 //{
2637 // // end of data
2638 // return 0;
2639 //}
2640
2641 // more data found
2642 // return 1;
2643 }
2644
2645 void street_index_close_compr(struct street_index_head *sih)
2646 {
2647 g_free(sih->inflator);
2648 sih->comp_status = 2;
2649 }
2650
2651 void town_index_close_compr(struct street_index_head *sih)
2652 {
2653 g_free(sih->t_inflator);
2654 sih->t_comp_status = 2;
2655 }
2656
2657 void street_index_init_compr(struct street_index_head *sih, long long size)
2658 {
2659 // decompress structure
2660 sih->inflator = g_new0(tinfl_decompressor, 1);
2661 sih->comp_status = 1;
2662 // decompress structure
2663
2664 // Decompression.
2665 sih->infile_size = (uint) size;
2666 sih->infile_remaining = sih->infile_size;
2667
2668 sih->next_in = s_inbuf;
2669 sih->avail_in = 0;
2670 sih->next_out = s_outbuf;
2671 sih->avail_out = OUT_BUF_SIZE2;
2672
2673 sih->data_count = 0;
2674
2675 tinfl_init(sih->inflator);
2676 }
2677
2678 void town_index_init_compr(struct street_index_head *sih, long long size)
2679 {
2680 // decompress structure
2681 sih->t_inflator = g_new0(tinfl_decompressor, 1);
2682 sih->t_comp_status = 1;
2683 // decompress structure
2684
2685 // Decompression.
2686 sih->t_infile_size = (uint) size;
2687 sih->t_infile_remaining = sih->t_infile_size;
2688
2689 sih->t_next_in = t_s_inbuf;
2690 sih->t_avail_in = 0;
2691 sih->t_next_out = t_s_outbuf;
2692 sih->t_avail_out = t_OUT_BUF_SIZE2;
2693
2694 sih->t_data_count = 0;
2695
2696 tinfl_init(sih->t_inflator);
2697 }
2698
2699 int street_index_decompress_data_block(struct street_index_head *sih)
2700 {
2701 // size_t total_in = 0, total_out = 0;
2702 // long file_loc;
2703
2704 // Decompression.
2705 for (;;)
2706 {
2707 sih->in_bytes = 0;
2708 sih->out_bytes = 0;
2709 if (!sih->avail_in)
2710 {
2711 // Input buffer is empty, so read more bytes from input file.
2712 uint n = my_min(IN_BUF_SIZE2, sih->infile_remaining);
2713
2714 //dbg(0, "reading bytes:%d remain=%d\n", n, sih->infile_remaining);
2715
2716 if (fread(s_inbuf, 1, n, sih->sif) != n)
2717 {
2718 //printf("Failed reading from input file!\n");
2719 dbg(0, "Failed reading from input file!\n");
2720 //g_free(sih->inflator);
2721 return -1;
2722 }
2723
2724 sih->next_in = s_inbuf;
2725 sih->avail_in = n;
2726
2727 sih->infile_remaining -= n;
2728 }
2729
2730 sih->in_bytes = sih->avail_in;
2731 sih->out_bytes = sih->avail_out;
2732 sih->miniz_status = tinfl_decompress(sih->inflator, (const mz_uint8 *) sih->next_in, &sih->in_bytes, s_outbuf, (mz_uint8 *) sih->next_out, &sih->out_bytes, (sih->infile_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0) | TINFL_FLAG_PARSE_ZLIB_HEADER);
2733
2734 sih->avail_in -= sih->in_bytes;
2735 sih->next_in = (const mz_uint8 *) sih->next_in + sih->in_bytes;
2736 //total_in += sih->in_bytes;
2737
2738 sih->avail_out -= sih->out_bytes;
2739 sih->next_out = (mz_uint8 *) sih->next_out + sih->out_bytes;
2740 //total_out += sih->out_bytes;
2741
2742 if ((sih->miniz_status <= TINFL_STATUS_DONE) || (!sih->avail_out))
2743 {
2744 // Output buffer is full, or decompression is done, so write buffer to output file.
2745 uint n = OUT_BUF_SIZE2 - (uint) sih->avail_out;
2746
2747 //dbg(0, "decompr: start=%p len=%d\n", (void *) sih->next_out, (int) n);
2748 //dbg(0, "decompr: start=%p len=%d\n", (void *) s_outbuf, (int) n);
2749 //dbg(0, "decompr: av in=%d av out=%d\n", sih->avail_in, sih->avail_out);
2750 //dbg(0, "decompr: nx in=%d nx out=%d\n", sih->next_in, sih->next_out);
2751
2752 //struct streets_index_data_block *tmp = (struct streets_index_data_block *)s_outbuf;
2753 //dbg(0,"data=%s, %d, %d, %lld\n", tmp->street_name, tmp->lat, tmp->lon, tmp->town_id);
2754
2755 //sih->next_out = s_outbuf;
2756 //sih->avail_out = OUT_BUF_SIZE2;
2757
2758 return (int) n;
2759
2760 //if (fwrite(s_outbuf, 1, n, pOutfile) != n)
2761 //{
2762 // // printf("Failed writing to output file!\n");
2763 // //g_free(inflator);
2764 // return;
2765 //}
2766 }
2767
2768 // If sih->miniz_status is <= TINFL_STATUS_DONE then either decompression is done or something went wrong.
2769 if (sih->miniz_status <= TINFL_STATUS_DONE)
2770 {
2771 if (sih->miniz_status == TINFL_STATUS_DONE)
2772 {
2773 // Decompression completed successfully.
2774 //dbg(0, "Decompression completed successfully\n");
2775 //break;
2776 return -2;
2777 }
2778 else
2779 {
2780 // Decompression failed.
2781 //printf("tinfl_decompress() failed with status %i!\n", sih->miniz_status);
2782 dbg(0, "tinfl_decompress() failed with status %i!\n", sih->miniz_status);
2783
2784 //g_free(inflator);
2785 return -1;
2786 }
2787 }
2788 }
2789
2790 //g_free(inflator);
2791 return -3;
2792
2793 }
2794
2795 int town_index_decompress_data_block(struct street_index_head *sih)
2796 {
2797 // size_t total_in = 0, total_out = 0;
2798 // long file_loc;
2799
2800 // Decompression.
2801 for (;;)
2802 {
2803 sih->t_in_bytes = 0;
2804 sih->t_out_bytes = 0;
2805 if (!sih->t_avail_in)
2806 {
2807 // Input buffer is empty, so read more bytes from input file.
2808 uint n = my_min(t_IN_BUF_SIZE2, sih->t_infile_remaining);
2809
2810 //dbg(0, "reading bytes:%d remain=%d\n", n, sih->t_infile_remaining);
2811
2812 if (fread(t_s_inbuf, 1, n, sih->sif) != n)
2813 {
2814 //printf("Failed reading from input file!\n");
2815 dbg(0, "Failed reading from input file!\n");
2816 //g_free(sih->inflator);
2817 return -1;
2818 }
2819
2820 sih->t_next_in = t_s_inbuf;
2821 sih->t_avail_in = n;
2822
2823 sih->t_infile_remaining -= n;
2824 }
2825
2826 sih->t_in_bytes = sih->t_avail_in;
2827 sih->t_out_bytes = sih->t_avail_out;
2828 sih->t_miniz_status = tinfl_decompress(sih->t_inflator, (const mz_uint8 *) sih->t_next_in, &sih->t_in_bytes, t_s_outbuf, (mz_uint8 *) sih->t_next_out, &sih->t_out_bytes, (sih->t_infile_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0) | TINFL_FLAG_PARSE_ZLIB_HEADER);
2829
2830 sih->t_avail_in -= sih->t_in_bytes;
2831 sih->t_next_in = (const mz_uint8 *) sih->t_next_in + sih->t_in_bytes;
2832 //total_in += sih->in_bytes;
2833
2834 sih->t_avail_out -= sih->t_out_bytes;
2835 sih->t_next_out = (mz_uint8 *) sih->t_next_out + sih->t_out_bytes;
2836 //total_out += sih->out_bytes;
2837
2838 if ((sih->t_miniz_status <= TINFL_STATUS_DONE) || (!sih->t_avail_out))
2839 {
2840 // Output buffer is full, or decompression is done, so write buffer to output file.
2841 uint n = t_OUT_BUF_SIZE2 - (uint) sih->t_avail_out;
2842
2843 //dbg(0, "decompr: start=%p len=%d\n", (void *) sih->next_out, (int) n);
2844 //dbg(0, "decompr: start=%p len=%d\n", (void *) s_outbuf, (int) n);
2845 //dbg(0, "decompr: av in=%d av out=%d\n", sih->avail_in, sih->avail_out);
2846 //dbg(0, "decompr: nx in=%d nx out=%d\n", sih->next_in, sih->next_out);
2847
2848 //struct town_index_data_block *tmpt = (struct town_index_data_block *)t_s_outbuf;
2849 //dbg(0,"data=%lld %s\n", tmpt->town_id, tmpt->town_name);
2850
2851 //sih->next_out = s_outbuf;
2852 //sih->avail_out = t_OUT_BUF_SIZE2;
2853
2854 return (int) n;
2855
2856 //if (fwrite(s_outbuf, 1, n, pOutfile) != n)
2857 //{
2858 // // printf("Failed writing to output file!\n");
2859 // //g_free(inflator);
2860 // return;
2861 //}
2862 }
2863
2864 // If sih->miniz_status is <= TINFL_STATUS_DONE then either decompression is done or something went wrong.
2865 if (sih->t_miniz_status <= TINFL_STATUS_DONE)
2866 {
2867 if (sih->t_miniz_status == TINFL_STATUS_DONE)
2868 {
2869 // Decompression completed successfully.
2870 //dbg(0, "Decompression completed successfully\n");
2871 //break;
2872 return -2;
2873 }
2874 else
2875 {
2876 // Decompression failed.
2877 //printf("tinfl_decompress() failed with status %i!\n", sih->miniz_status);
2878 dbg(0, "tinfl_decompress() failed with status %i!\n", sih->t_miniz_status);
2879
2880 //g_free(inflator);
2881 return -1;
2882 }
2883 }
2884 }
2885
2886 //g_free(inflator);
2887 return -3;
2888
2889 }
2890
2891 void street_index_close(struct street_index_head *sih)
2892 {
2893 g_free(sih->si_ib_mem);
2894 g_free(sih->ti_ib_mem);
2895 if (town_lookup_cache)
2896 {
2897 g_free(town_lookup_cache);
2898 town_lookup_cache = NULL;
2899 }
2900 fclose(sih->sif);
2901 g_free(sih);
2902 }
2903
2904
2905 // func defs
2906 void search_v2_work(char *addr, char *town, char* hn, int partial, struct jni_object *jni, const char* idxfile_name);
2907 void search_v2(char *addr, char *town, char* hn, int partial, struct jni_object *jni);
2908 // func defs
2909
2910
2911 #include <sys/types.h>
2912 #include <dirent.h>
2913
2914 void search_v2(char *addr, char *town, char* hn, int partial, struct jni_object *jni)
2915 {
2916 int len;
2917 int len2;
2918 int len3;
2919 char *last_four;
2920 DIR* dirp;
2921 struct dirent *dp;
2922
2923 len2 = strlen("navitmap_");
2924 len = len2 + 11; // should be 21 'navitmap_0%%.bin.idx'
2925
2926 // look for all the navitmap_0**.bin.idx files in mapdir, then call search in all of them
2927 dirp = opendir(navit_maps_dir);
2928 while ((dp = readdir(dirp)) != NULL)
2929 {
2930 if ((strlen(dp->d_name) == len) && (!strncmp(dp->d_name, "navitmap_", len2)))
2931 {
2932 //dbg(0, "2 file=%s\n", dp->d_name);
2933 len3 = strlen(dp->d_name);
2934 last_four = &dp->d_name[len3-4];
2935 //dbg(0, "3 l4=%s\n", last_four);
2936 if (!strcmp(last_four, ".idx"))
2937 {
2938 search_v2_work(addr, town, hn, partial, jni, dp->d_name);
2939 }
2940 }
2941 }
2942 closedir(dirp);
2943
2944 }
2945
2946 void search_v2_work(char *addr, char *town, char* hn, int partial, struct jni_object *jni, const char* idxfile_name)
2947 {
2948 char *buffer = NULL;
2949 float lat;
2950 float lng;
2951 char *address;
2952 char *address2;
2953 char *townname = NULL;
2954 char *addr_copy;
2955 char *addr2;
2956 char *addr3;
2957 char *addr3a;
2958 char *town_fold;
2959 char *tt;
2960 int i;
2961 int j;
2962 int br;
2963 int charlen;
2964 int found;
2965 int starts_with_utf8 = 0;
2966 int nd_with_utf8 = 0;
2967 int want_result;
2968 struct coord c3;
2969 static const char *alpha = "abcdefghijklmnopqrstuvwxyz";
2970 char tmp_letter[STREET_INDEX_STREET_NAME_SIZE];
2971 struct street_index_head *sih;
2972
2973
2974 if ((!addr) || (strlen(addr) < 1))
2975 {
2976 return;
2977 }
2978
2979 // prepare search string
2980 addr2 = linguistics_casefold(addr);
2981 if (addr2)
2982 {
2983 addr3 = linguistics_remove_all_specials(addr2);
2984 if (addr3)
2985 {
2986 g_free(addr2);
2987 addr2 = addr3;
2988 }
2989 addr3 = linguistics_expand_special(addr2, 1);
2990 if (addr3)
2991 {
2992 g_free(addr2);
2993 addr2 = addr3;
2994 }
2995 addr_copy = addr2;
2996 }
2997 else
2998 {
2999 addr2 = g_strdup(addr);
3000 addr_copy = addr2;
3001 }
3002
3003 // prepare town search string
3004 town_fold = linguistics_fold_and_prepare_complete(town, 0);
3005
3006
3007 //dbg(0,"town=%s townfold=%s street=%s hn=%s\n", town, town_fold, addr_copy, hn);
3008
3009 sih = street_index_init(idxfile_name);
3010
3011 // is first letter ascii or UTF-8?
3012 addr3 = g_utf8_find_next_char(addr_copy, NULL);
3013 charlen = addr3 - addr_copy;
3014 if (charlen > 1)
3015 {
3016 starts_with_utf8 = 1;
3017 }
3018 //dbg(0, "charlen=%d starts_with_utf8=%d\n", charlen, starts_with_utf8);
3019
3020 // is second letter ascii or UTF-8?
3021 addr3a = g_utf8_find_next_char(addr3, NULL);
3022 charlen = addr3a - addr3;
3023 if (charlen > 1)
3024 {
3025 nd_with_utf8 = 1;
3026 }
3027 //dbg(0, "charlen=%d nd_with_utf8=%d\n", charlen, nd_with_utf8);
3028
3029
3030 // find starting letter of search string
3031 found = (703 - 1); // 26+1 letters ((26+1)*26 + 1) = 703
3032 br = 0;
3033 if (starts_with_utf8 == 0)
3034 {
3035 // check the first letter
3036 for (i = 0; i < 26; i++)
3037 {
3038 if (addr_copy[0] == alpha[i])
3039 {
3040 if ((strlen(addr_copy) > 1) && (nd_with_utf8 == 0))
3041 {
3042 //dbg(0, "i=%d\n", i);
3043 // check the second letter
3044 for (j = 0; j < 26; j++)
3045 {
3046 //dbg(0, "j=%d\n", j);
3047 if (addr_copy[1] == alpha[j])
3048 {
3049 found = (27 * i) + j;
3050 br = 1;
3051 break;
3052 }
3053 }
3054 if (br == 0)
3055 {
3056 // second letter has no match, use generic first letter block
3057 found = (27 * i) + 26;
3058 }
3059 br = 1;
3060 break;
3061 }
3062 else
3063 {
3064 // use generic first letter block
3065 found = (27 * i) + 26;
3066 br = 1;
3067 break;
3068 }
3069 }
3070
3071 if (br)
3072 {
3073 break;
3074 }
3075 }
3076 }
3077
3078 //dbg(0, "found pos=%d\n", found);
3079
3080 street_index_setpos(sih, found);
3081 int found_data = 0;
3082 //int ddd = 0;
3083
3084 while (street_index_read_data(sih))
3085 {
3086 //ddd++;
3087
3088 //if (ddd > 3)
3089 //{
3090 // break;
3091 //}
3092
3093 if (offline_search_break_searching == 1)
3094 {
3095 break;
3096 }
3097
3098 //dbg(0,"data=%s addr=%s\n", sih->si_db_ptr->street_name, addr_copy);
3099 if (!ascii_cmp_local_faster(sih->si_db_ptr->street_name, addr_copy, 1))
3100 {
3101 found_data = 1;
3102 if ((partial == 1) || (!ascii_cmp_local_faster(sih->si_db_ptr->street_name, addr_copy, partial)))
3103 {
3104 townname = town_index_lookup(sih, sih->si_db_ptr->town_id);
3105
3106 // if we also have a search-town-name then check here
3107 if ((!town_fold)||(strlen(town_fold) < 1))
3108 {
3109 want_result = 1;
3110 }
3111 else
3112 {
3113 tt = linguistics_fold_and_prepare_complete(townname, 0);
3114 want_result = 1-(linguistics_compare_anywhere(tt, town_fold));
3115 //dbg(0, "want_result=%d tt=%s\n", want_result, tt);
3116 }
3117
3118 if (want_result == 1)
3119 {
3120
3121 // check for housenumber
3122 if ((hn != NULL) && (strlen(hn) > 0))
3123 {
3124 // now set coord of this item/street
3125 c3.y = sih->si_db_ptr->lat;
3126 c3.x = sih->si_db_ptr->lon;
3127 search_address_housenumber_for_street(hn, sih->si_db_ptr->street_name, townname, &c3, partial, jni);
3128 }
3129
3130 if (townname != NULL)
3131 {
3132 address = g_strdup_printf("%s, %s", sih->si_db_ptr->street_name, townname);
3133 }
3134 else
3135 {
3136 address = g_strdup_printf("%s", sih->si_db_ptr->street_name);
3137 }
3138
3139
3140 if (strlen(address) > 100)
3141 {
3142 address2 = address;
3143 address2[101] = '\0';
3144 address2 = linguistics_check_utf8_string(address2);
3145 }
3146 else
3147 {
3148 address2 = address;
3149 }
3150 buffer = g_strdup_printf("STR:H0L0:%d:%d:%.101s", sih->si_db_ptr->lat, sih->si_db_ptr->lon, address2);
3151 #ifdef HAVE_API_ANDROID
3152 // return results to android as they come in ...
3153 android_return_search_result(jni, buffer);
3154 #endif
3155 if (townname)
3156 {
3157 g_free(townname);
3158 townname = NULL;
3159 }
3160
3161 if (address)
3162 {
3163 g_free(address);
3164 address = NULL;
3165 }
3166
3167 if (buffer)
3168 {
3169 g_free(buffer);
3170 buffer = NULL;
3171 }
3172 }
3173 }
3174 }
3175 else
3176 {
3177 if (found_data == 1)
3178 {
3179 // no more matching data, stop searching
3180 break;
3181 }
3182 }
3183 }
3184 g_free(addr_copy);
3185 street_index_close(sih);
3186
3187 }
3188

   
Visit the ZANavi Wiki