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

Diff of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 28 Revision 30
66struct suffix 66struct suffix
67{ 67{
68 char *fullname; 68 char *fullname;
69 char *abbrev; 69 char *abbrev;
70 int sex; 70 int sex;
71} suffixes[] = 71} suffixes[] = { { "weg", NULL, 1 }, { "platz", "pl.", 1 }, { "ring", NULL, 1 }, { "allee", NULL, 2 }, { "gasse", NULL, 2 }, { "straße", "str.", 2 }, { "strasse", NULL, 2 }, };
72{
73{ "weg", NULL, 1 },
74{ "platz", "pl.", 1 },
75{ "ring", NULL, 1 },
76{ "allee", NULL, 2 },
77{ "gasse", NULL, 2 },
78{ "straße", "str.", 2 },
79{ "strasse", NULL, 2 }, };
80 72
81struct navigation 73struct navigation
82{ 74{
83 struct route *route; 75 struct route *route;
84 struct map *map; 76 struct map *map;
102 int tell_street_name; 94 int tell_street_name;
103 int delay; 95 int delay;
104 int curr_delay; 96 int curr_delay;
105}; 97};
106 98
107int distances[] =
108{ 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 }; 99int distances[] = { 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 };
109 100
110struct navigation_command 101struct navigation_command
111{ 102{
112 struct navigation_itm *itm; 103 struct navigation_itm *itm;
113 struct navigation_command *next; 104 struct navigation_command *next;
150static int angle_opposite(int angle) 141static int angle_opposite(int angle)
151{ 142{
152 return ((angle + 180) % 360); 143 return ((angle + 180) % 360);
153} 144}
154 145
155int navigation_get_attr(struct navigation *this_, enum attr_type type, 146int navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
156 struct attr *attr, struct attr_iter *iter)
157{ 147{
158 struct map_rect *mr; 148 struct map_rect *mr;
159 struct item *item; 149 struct item *item;
160 dbg(1, "enter %s\n", attr_to_name(type)); 150 dbg(1, "enter %s\n", attr_to_name(type));
161 switch (type) 151 switch (type)
167 case attr_length: 157 case attr_length:
168 case attr_navigation_speech: 158 case attr_navigation_speech:
169 mr = map_rect_new(this_->map, NULL); 159 mr = map_rect_new(this_->map, NULL);
170 while ((item = map_rect_get_item(mr))) 160 while ((item = map_rect_get_item(mr)))
171 { 161 {
172 if (item->type != type_nav_none && item->type 162 if (item->type != type_nav_none && item->type != type_nav_position)
173 != type_nav_position)
174 { 163 {
175 if (type == attr_item_type) 164 if (type == attr_item_type)
176 attr->u.item_type = item->type; 165 attr->u.item_type = item->type;
177 else 166 else
178 { 167 {
238 } 227 }
239 228
240 return ret; 229 return ret;
241} 230}
242 231
243int navigation_set_announce(struct navigation *this_, enum item_type type, 232int navigation_set_announce(struct navigation *this_, enum item_type type, int *level)
244 int *level)
245{ 233{
246 int i; 234 int i;
247 if (type < route_item_first || type > route_item_last) 235 if (type < route_item_first || type > route_item_last)
248 { 236 {
249 dbg(0, "street type %d out of range [%d,%d]", type, route_item_first, 237 dbg(0, "street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
250 route_item_last);
251 return 0; 238 return 0;
252 } 239 }
253 for (i = 0; i < 3; i++) 240 for (i = 0; i < 3; i++)
254 this_->announce[type - route_item_first][i] = level[i]; 241 this_->announce[type - route_item_first][i] = level[i];
255 return 1; 242 return 1;
256} 243}
257 244
258static int navigation_get_announce_level(struct navigation *this_, 245static int navigation_get_announce_level(struct navigation *this_, enum item_type type, int dist)
259 enum item_type type, int dist)
260{ 246{
261 int i; 247 int i;
262 248
263 if (type < route_item_first || type > route_item_last) 249 if (type < route_item_first || type > route_item_last)
264 return -1; 250 return -1;
299 int dest_count; 285 int dest_count;
300 struct navigation_itm *next; 286 struct navigation_itm *next;
301 struct navigation_itm *prev; 287 struct navigation_itm *prev;
302}; 288};
303 289
304static int is_way_allowed(struct navigation *nav, struct navigation_way *way, 290static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode);
305 int mode);
306 291
307static int navigation_get_announce_level_cmd(struct navigation *this_, 292static int navigation_get_announce_level_cmd(struct navigation *this_, struct navigation_itm *itm, struct navigation_command *cmd, int distance)
308 struct navigation_itm *itm, struct navigation_command *cmd,
309 int distance)
310{ 293{
311 int level2, level = navigation_get_announce_level(this_, 294 int level2, level = navigation_get_announce_level(this_, itm->way.item.type, distance);
312 itm->way.item.type, distance);
313 if (this_->cmd_first->itm->prev) 295 if (this_->cmd_first->itm->prev)
314 { 296 {
315 level2 = navigation_get_announce_level(this_, 297 level2 = navigation_get_announce_level(this_, cmd->itm->prev->way.item.type, distance);
316 cmd->itm->prev->way.item.type, distance);
317 if (level2 > level) 298 if (level2 > level)
318 level = level2; 299 level = level2;
319 } 300 }
320 return level; 301 return level;
321} 302}
579 i++; 560 i++;
580 return distances[i - 1]; 561 return distances[i - 1];
581} 562}
582 563
583static char * 564static char *
584get_distance(struct navigation *nav, int dist, enum attr_type type, 565get_distance(struct navigation *nav, int dist, enum attr_type type, int is_length)
585 int is_length)
586{ 566{
587 int imperial = 0, vocabulary = 65535; 567 int imperial = 0, vocabulary = 65535;
588 struct attr attr; 568 struct attr attr;
589 569
590 if (type == attr_navigation_long) 570 if (type == attr_navigation_long)
608 return g_strdup_printf(_("in %d m"), dist); 588 return g_strdup_printf(_("in %d m"), dist);
609 } 589 }
610 } 590 }
611 if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL)) 591 if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL))
612 imperial = attr.u.num; 592 imperial = attr.u.num;
613 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, 593 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, &attr, NULL))
614 &attr, NULL))
615 vocabulary = attr.u.num; 594 vocabulary = attr.u.num;
616 if (imperial) 595 if (imperial)
617 { 596 {
618 if (dist * FEET_PER_METER < vocabulary_last(vocabulary)) 597 if (dist * FEET_PER_METER < vocabulary_last(vocabulary))
619 { 598 {
669 } 648 }
670 } 649 }
671 } 650 }
672 if (imperial) 651 if (imperial)
673 { 652 {
674 dist = round_for_vocabulary(vocabulary, 653 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000);
675 dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000);
676 } 654 }
677 else 655 else
678 { 656 {
679 dist = round_for_vocabulary(vocabulary, dist, 1000); 657 dist = round_for_vocabulary(vocabulary, dist, 1000);
680 } 658 }
700#ifdef HAVE_API_ANDROID 678#ifdef HAVE_API_ANDROID
701#ifdef NAVIT_SAY_DEBUG_PRINT 679#ifdef NAVIT_SAY_DEBUG_PRINT
702 android_send_generic_text(1,"+*#O:in %d.%d miles\n"); 680 android_send_generic_text(1,"+*#O:in %d.%d miles\n");
703#endif 681#endif
704#endif 682#endif
705 return g_strdup_printf(_("in %d.%d miles"), dist / 1000, 683 return g_strdup_printf(_("in %d.%d miles"), dist / 1000, rem);
706 rem);
707 } 684 }
708 } 685 }
709 else 686 else
710 { 687 {
711 if (is_length) 688 if (is_length)
713#ifdef HAVE_API_ANDROID 690#ifdef HAVE_API_ANDROID
714#ifdef NAVIT_SAY_DEBUG_PRINT 691#ifdef NAVIT_SAY_DEBUG_PRINT
715 android_send_generic_text(1,"+*#O:%d.%d kilometers\n"); 692 android_send_generic_text(1,"+*#O:%d.%d kilometers\n");
716#endif 693#endif
717#endif 694#endif
718 return g_strdup_printf(_("%d.%d kilometers"), dist / 1000, 695 return g_strdup_printf(_("%d.%d kilometers"), dist / 1000, rem);
719 rem);
720 } 696 }
721 else 697 else
722 { 698 {
723#ifdef HAVE_API_ANDROID 699#ifdef HAVE_API_ANDROID
724#ifdef NAVIT_SAY_DEBUG_PRINT 700#ifdef NAVIT_SAY_DEBUG_PRINT
725 android_send_generic_text(1,"+*#O:in %d.%d kilometers\n"); 701 android_send_generic_text(1,"+*#O:in %d.%d kilometers\n");
726#endif 702#endif
727#endif 703#endif
728 return g_strdup_printf(_("in %d.%d kilometers"), 704 return g_strdup_printf(_("in %d.%d kilometers"), dist / 1000, rem);
729 dist / 1000, rem);
730 } 705 }
731 } 706 }
732 } 707 }
733 } 708 }
734 if (imperial) 709 if (imperial)
735 { 710 {
736 if (is_length) 711 if (is_length)
737 return g_strdup_printf(
738 ngettext("one mile", "%d miles", dist / 1000), dist / 1000); 712 return g_strdup_printf(ngettext("one mile", "%d miles", dist / 1000), dist / 1000);
739 else 713 else
740 return g_strdup_printf( 714 return g_strdup_printf(ngettext("in one mile", "in %d miles", dist / 1000), dist / 1000);
741 ngettext("in one mile", "in %d miles", dist / 1000),
742 dist / 1000);
743 } 715 }
744 else 716 else
745 { 717 {
746 if (is_length) 718 if (is_length)
747 { 719 {
748#ifdef HAVE_API_ANDROID 720#ifdef HAVE_API_ANDROID
749#ifdef NAVIT_SAY_DEBUG_PRINT 721#ifdef NAVIT_SAY_DEBUG_PRINT
750 android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n"); 722 android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n");
751#endif 723#endif
752#endif 724#endif
753 return g_strdup_printf(
754 ngettext("one kilometer", "%d kilometers", dist / 1000), 725 return g_strdup_printf(ngettext("one kilometer", "%d kilometers", dist / 1000), dist / 1000);
755 dist / 1000);
756 } 726 }
757 else 727 else
758 { 728 {
759#ifdef HAVE_API_ANDROID 729#ifdef HAVE_API_ANDROID
760#ifdef NAVIT_SAY_DEBUG_PRINT 730#ifdef NAVIT_SAY_DEBUG_PRINT
761 android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n"); 731 android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n");
762#endif 732#endif
763#endif 733#endif
764 return g_strdup_printf( 734 return g_strdup_printf(ngettext("in one kilometer", "in %d kilometers", dist / 1000), dist / 1000);
765 ngettext("in one kilometer", "in %d kilometers",
766 dist / 1000), dist / 1000);
767 } 735 }
768 } 736 }
769} 737}
770 738
771/** 739/**
821 789
822 if (w->dir < 0) 790 if (w->dir < 0)
823 { 791 {
824 if (item_coord_get(ritem, cbuf, 2) != 2) 792 if (item_coord_get(ritem, cbuf, 2) != 2)
825 { 793 {
826 dbg(1,
827 "Using calculate_angle() with a less-than-two-coords-item?\n"); 794 dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
828 map_rect_destroy(mr); 795 map_rect_destroy(mr);
829 return; 796 return;
830 } 797 }
831 798
832 while (item_coord_get(ritem, &c, 1)) 799 while (item_coord_get(ritem, &c, 1))
838 } 805 }
839 else 806 else
840 { 807 {
841 if (item_coord_get(ritem, cbuf, 2) != 2) 808 if (item_coord_get(ritem, cbuf, 2) != 2)
842 { 809 {
843 dbg(1,
844 "Using calculate_angle() with a less-than-two-coords-item?\n"); 810 dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
845 map_rect_destroy(mr); 811 map_rect_destroy(mr);
846 return; 812 return;
847 } 813 }
848 c = cbuf[0]; 814 c = cbuf[0];
849 cbuf[0] = cbuf[1]; 815 cbuf[0] = cbuf[1];
863 * 829 *
864 * @param from The first item 830 * @param from The first item
865 * @param to The last item 831 * @param to The last item
866 * @return The travel time in seconds, or -1 on error 832 * @return The travel time in seconds, or -1 on error
867 */ 833 */
868static int navigation_time(struct navigation_itm *from, 834static int navigation_time(struct navigation_itm *from, struct navigation_itm *to)
869 struct navigation_itm *to)
870{ 835{
871 struct navigation_itm *cur; 836 struct navigation_itm *cur;
872 int time; 837 int time;
873 838
874 time = 0; 839 time = 0;
921 * and the next navigation item are excluded. 886 * and the next navigation item are excluded.
922 * 887 *
923 * @param itm The item that should be updated 888 * @param itm The item that should be updated
924 * @param graph_map The route graph's map that these items are on 889 * @param graph_map The route graph's map that these items are on
925 */ 890 */
926static void navigation_itm_ways_update(struct navigation_itm *itm, 891static void navigation_itm_ways_update(struct navigation_itm *itm, struct map *graph_map)
927 struct map *graph_map)
928{ 892{
929 struct map_selection coord_sel; 893 struct map_selection coord_sel;
930 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map 894 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
931 struct item *i, *sitem; 895 struct item *i, *sitem;
932 struct attr sitem_attr, direction_attr; 896 struct attr sitem_attr, direction_attr;
964 continue; 928 continue;
965 } 929 }
966 930
967 if (!item_attr_get(i, attr_street_item, &sitem_attr)) 931 if (!item_attr_get(i, attr_street_item, &sitem_attr))
968 { 932 {
969 dbg(1,
970 "Got no street item for route graph item in entering_straight()\n"); 933 dbg(1, "Got no street item for route graph item in entering_straight()\n");
971 continue; 934 continue;
972 } 935 }
973 936
974 if (!item_attr_get(i, attr_direction, &direction_attr)) 937 if (!item_attr_get(i, attr_direction, &direction_attr))
975 { 938 {
976 continue; 939 continue;
977 } 940 }
978 941
979 sitem = sitem_attr.u.item; 942 sitem = sitem_attr.u.item;
980 if (sitem->type == type_street_turn_restriction_no || sitem->type 943 if (sitem->type == type_street_turn_restriction_no || sitem->type == type_street_turn_restriction_only)
981 == type_street_turn_restriction_only)
982 continue; 944 continue;
983 945
984 if (item_is_equal(itm->way.item, *sitem) || ((itm->prev) 946 if (item_is_equal(itm->way.item, *sitem) || ((itm->prev) && item_is_equal(itm->prev->way.item, *sitem)))
985 && item_is_equal(itm->prev->way.item, *sitem)))
986 { 947 {
987 continue; 948 continue;
988 } 949 }
989 950
990 l = w; 951 l = w;
998 map_rect_destroy(g_rect); 959 map_rect_destroy(g_rect);
999 960
1000 itm->way.next = w; 961 itm->way.next = w;
1001} 962}
1002 963
1003static void navigation_destroy_itms_cmds(struct navigation *this_, 964static void navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *end)
1004 struct navigation_itm *end)
1005{ 965{
1006 struct navigation_itm *itm; 966 struct navigation_itm *itm;
1007 struct navigation_command *cmd; 967 struct navigation_command *cmd;
1008 // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end); 968 // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end);
1009 if (this_->cmd_first) 969 if (this_->cmd_first)
1040 // dbg(0, "end wrong\n"); 1000 // dbg(0, "end wrong\n");
1041 } 1001 }
1042 // dbg(2, "ret this_->first=%p this_->cmd_first=%p\n", this_->first, this_->cmd_first); 1002 // dbg(2, "ret this_->first=%p this_->cmd_first=%p\n", this_->first, this_->cmd_first);
1043} 1003}
1044 1004
1045static void navigation_itm_update(struct navigation_itm *itm, 1005static void navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
1046 struct item *ritem)
1047{ 1006{
1048 struct attr length, time, speed; 1007 struct attr length, time, speed;
1049 1008
1050 if (!item_attr_get(ritem, attr_length, &length)) 1009 if (!item_attr_get(ritem, attr_length, &length))
1051 { 1010 {
1117 } 1076 }
1118 1077
1119 sitem = sitem_attr.u.item; 1078 sitem = sitem_attr.u.item;
1120 if (item_is_equal(itm->way.item, *sitem)) 1079 if (item_is_equal(itm->way.item, *sitem))
1121 { 1080 {
1122 if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num 1081 if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num & AF_ROUNDABOUT))
1123 & AF_ROUNDABOUT))
1124 { 1082 {
1125 map_rect_destroy(g_rect); 1083 map_rect_destroy(g_rect);
1126 return 1; 1084 return 1;
1127 } 1085 }
1128 } 1086 }
1233 * @param from The navigation item which should form the start 1191 * @param from The navigation item which should form the start
1234 * @param to The navigation item which should form the end 1192 * @param to The navigation item which should form the end
1235 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right 1193 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
1236 * @return The number of possibilities to turn or -1 on error 1194 * @return The number of possibilities to turn or -1 on error
1237 */ 1195 */
1238static int count_possible_turns(struct navigation *nav, 1196static int count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction)
1239 struct navigation_itm *from, struct navigation_itm *to, int direction)
1240{ 1197{
1241 int count; 1198 int count;
1242 struct navigation_itm *curr; 1199 struct navigation_itm *curr;
1243 struct navigation_way *w; 1200 struct navigation_way *w;
1244 1201
1340 * 1297 *
1341 * @param old The first item to be checked 1298 * @param old The first item to be checked
1342 * @param new The second item to be checked 1299 * @param new The second item to be checked
1343 * @return True if both old and new are on the same street 1300 * @return True if both old and new are on the same street
1344 */ 1301 */
1345static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, 1302static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2)
1346 char *new_name2)
1347{ 1303{
1348 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1)) 1304 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1))
1349 { 1305 {
1350 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1); 1306 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
1351 return 1; 1307 return 1;
1478 return 0; 1434 return 0;
1479 } 1435 }
1480 1436
1481} 1437}
1482 1438
1483static int is_way_allowed(struct navigation *nav, struct navigation_way *way, 1439static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
1484 int mode)
1485{ 1440{
1486 if (!nav->vehicleprofile) 1441 if (!nav->vehicleprofile)
1487 { 1442 {
1488 return 1; 1443 return 1;
1489 } 1444 }
1490 return !way->flags || ((way->flags 1445 return !way->flags || ((way->flags & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask : nav->vehicleprofile->flags_reverse_mask)) == nav->vehicleprofile->flags);
1491 & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask
1492 : nav->vehicleprofile->flags_reverse_mask))
1493 == nav->vehicleprofile->flags);
1494} 1446}
1495 1447
1496/** 1448/**
1497 * @brief Checks if navit has to create a maneuver to drive from old to new 1449 * @brief Checks if navit has to create a maneuver to drive from old to new
1498 * 1450 *
1503 * @param new The new navigation item, where we're going to 1455 * @param new The new navigation item, where we're going to
1504 * @param delta The angle the user has to steer to navigate from old to new 1456 * @param delta The angle the user has to steer to navigate from old to new
1505 * @param reason A text string explaining how the return value resulted 1457 * @param reason A text string explaining how the return value resulted
1506 * @return True if navit should guide the user, false otherwise 1458 * @return True if navit should guide the user, false otherwise
1507 */ 1459 */
1508static int maneuver_required2(struct navigation *nav, 1460static int maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, char **reason)
1509 struct navigation_itm *old, struct navigation_itm *new, int *delta,
1510 char **reason)
1511{ 1461{
1512 int ret = 0, d, dw, dlim; 1462 int ret = 0, d, dw, dlim;
1513 char *r = NULL; 1463 char *r = NULL;
1514 struct navigation_way *w; 1464 struct navigation_way *w;
1515 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, 1465 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, is_same_street;
1516 is_same_street;
1517 1466
1518 //dbg(1, "enter %p %p %p\n", old, new, delta); 1467 //dbg(1, "enter %p %p %p\n", old, new, delta);
1519 d = angle_delta(old->angle_end, new->way.angle2); 1468 d = angle_delta(old->angle_end, new->way.angle2);
1520 if (!new->way.next) 1469 if (!new->way.next)
1521 { 1470 {
1522 /* No announcement necessary */ 1471 /* No announcement necessary */
1523 r = "no: Only one possibility"; 1472 r = "no: Only one possibility";
1524 } 1473 }
1525 else if (!new->way.next->next && new->way.next->item.type == type_ramp 1474 else if (!new->way.next->next && new->way.next->item.type == type_ramp && !is_way_allowed(nav, new->way.next, 1))
1526 && !is_way_allowed(nav, new->way.next, 1))
1527 { 1475 {
1528 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */ 1476 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
1529 r = "no: Only ramp"; 1477 r = "no: Only ramp";
1530 } 1478 }
1531 if (!r) 1479 if (!r)
1532 { 1480 {
1533 if ((old->way.flags & AF_ROUNDABOUT) && !(new->way.flags 1481 if ((old->way.flags & AF_ROUNDABOUT) && !(new->way.flags & AF_ROUNDABOUT))
1534 & AF_ROUNDABOUT))
1535 { 1482 {
1536 r = "yes: leaving roundabout"; 1483 r = "yes: leaving roundabout";
1537 ret = 1; 1484 ret = 1;
1538 } 1485 }
1539 else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags 1486 else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT))
1540 & AF_ROUNDABOUT))
1541 { 1487 {
1542 r = "no: entering roundabout"; 1488 r = "no: entering roundabout";
1543 } 1489 }
1544 else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags 1490 else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT))
1545 & AF_ROUNDABOUT))
1546 r = "no: staying in roundabout"; 1491 r = "no: staying in roundabout";
1547 } 1492 }
1548 if (!r && abs(d) > 75) 1493 if (!r && abs(d) > 75)
1549 { 1494 {
1550 /* always make an announcement if you have to make a sharp turn */ 1495 /* always make an announcement if you have to make a sharp turn */
1554 cat = maneuver_category(old->way.item.type); 1499 cat = maneuver_category(old->way.item.type);
1555 ncat = maneuver_category(new->way.item.type); 1500 ncat = maneuver_category(new->way.item.type);
1556 if (!r) 1501 if (!r)
1557 { 1502 {
1558 /* Check whether the street keeps its name */ 1503 /* Check whether the street keeps its name */
1559 is_same_street = is_same_street2(old->way.name1, old->way.name2, 1504 is_same_street = is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
1560 new->way.name1, new->way.name2);
1561 w = new->way.next; 1505 w = new->way.next;
1562 maxcat = -1; 1506 maxcat = -1;
1563 while (w) 1507 while (w)
1564 { 1508 {
1565 dw = angle_delta(old->angle_end, w->angle2); 1509 dw = angle_delta(old->angle_end, w->angle2);
1574 right = dw; 1518 right = dw;
1575 } 1519 }
1576 wcat = maneuver_category(w->item.type); 1520 wcat = maneuver_category(w->item.type);
1577 /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then 1521 /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then
1578 we can't use the same name criterium */ 1522 we can't use the same name criterium */
1579 if (is_same_street && is_same_street2(old->way.name1, 1523 if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (cat != 7 || wcat != 7) && is_way_allowed(nav, w, 2))
1580 old->way.name2, w->name1, w->name2) && (cat != 7 || wcat
1581 != 7) && is_way_allowed(nav, w, 2))
1582 is_same_street = 0; 1524 is_same_street = 0;
1583 /* Even if the ramp has the same name, announce it */ 1525 /* Even if the ramp has the same name, announce it */
1584 if (new->way.item.type == type_ramp && old->way.item.type 1526 if (new->way.item.type == type_ramp && old->way.item.type != type_ramp)
1585 != type_ramp)
1586 is_same_street = 0; 1527 is_same_street = 0;
1587 /* Mark if the street has a higher or the same category */ 1528 /* Mark if the street has a higher or the same category */
1588 if (wcat > maxcat) 1529 if (wcat > maxcat)
1589 maxcat = wcat; 1530 maxcat = wcat;
1590 w = w->next; 1531 w = w->next;
1727{ 1668{
1728 struct navigation_command *ret=g_new0(struct navigation_command, 1); 1669 struct navigation_command *ret=g_new0(struct navigation_command, 1);
1729 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta); 1670 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
1730 ret->delta = delta; 1671 ret->delta = delta;
1731 ret->itm = itm; 1672 ret->itm = itm;
1732 if (itm && itm->prev && itm->way.next && itm->prev->way.next 1673 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags & AF_ROUNDABOUT))
1733 && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags
1734 & AF_ROUNDABOUT))
1735 { 1674 {
1736 int len = 0; 1675 int len = 0;
1737 int angle = 0; 1676 int angle = 0;
1738 int entry_angle; 1677 int entry_angle;
1739 struct navigation_itm *itm2 = itm->prev; 1678 struct navigation_itm *itm2 = itm->prev;
1740 int exit_angle = angle_median(itm->prev->angle_end, 1679 int exit_angle = angle_median(itm->prev->angle_end, itm->way.next->angle2);
1741 itm->way.next->angle2);
1742 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2); 1680 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
1743 while (itm2 && (itm2->way.flags & AF_ROUNDABOUT)) 1681 while (itm2 && (itm2->way.flags & AF_ROUNDABOUT))
1744 { 1682 {
1745 len += itm2->length; 1683 len += itm2->length;
1746 angle = itm2->angle_end; 1684 angle = itm2->angle_end;
1747 itm2 = itm2->prev; 1685 itm2 = itm2->prev;
1748 } 1686 }
1749 if (itm2 && itm2->next && itm2->next->way.next) 1687 if (itm2 && itm2->next && itm2->next->way.next)
1750 { 1688 {
1751 itm2 = itm2->next; 1689 itm2 = itm2->next;
1752 entry_angle = angle_median(angle_opposite(itm2->way.angle2), 1690 entry_angle = angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
1753 itm2->way.next->angle2);
1754 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2); 1691 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
1755 } 1692 }
1756 else 1693 else
1757 { 1694 {
1758 entry_angle = angle_opposite(angle); 1695 entry_angle = angle_opposite(angle);
1820 1757
1821 return ret; 1758 return ret;
1822} 1759}
1823 1760
1824static char * 1761static char *
1825navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, 1762navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
1826 struct navigation_itm *next, char *prefix)
1827{ 1763{
1828 char *ret = NULL, *name1, *sep, *name2; 1764 char *ret = NULL, *name1, *sep, *name2;
1829 char *n1, *n2; 1765 char *n1, *n2;
1830 int i, sex; 1766 int i, sex;
1831 int vocabulary1 = 65535; 1767 int vocabulary1 = 65535;
1832 int vocabulary2 = 65535; 1768 int vocabulary2 = 65535;
1833 struct attr attr; 1769 struct attr attr;
1834 1770
1835 if (!prefix) 1771 if (!prefix)
1836 prefix = ""; 1772 prefix = "";
1837 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, 1773 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
1838 &attr, NULL))
1839 vocabulary1 = attr.u.num; 1774 vocabulary1 = attr.u.num;
1840 if (nav->speech && speech_get_attr(nav->speech, 1775 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
1841 attr_vocabulary_name_systematic, &attr, NULL))
1842 vocabulary2 = attr.u.num; 1776 vocabulary2 = attr.u.num;
1843 n1 = itm->way.name1; 1777 n1 = itm->way.name1;
1844 n2 = itm->way.name2; 1778 n2 = itm->way.name2;
1845 if (!vocabulary1) 1779 if (!vocabulary1)
1846 n1 = NULL; 1780 n1 = NULL;
1850 { 1784 {
1851 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type); 1785 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
1852 1786
1853 if (next->way.item.type == type_ramp) 1787 if (next->way.item.type == type_ramp)
1854 return NULL; 1788 return NULL;
1855 if (itm->way.item.type == type_highway_city || itm->way.item.type 1789 if (itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land)
1856 == type_highway_land)
1857 { 1790 {
1858#ifdef HAVE_API_ANDROID 1791#ifdef HAVE_API_ANDROID
1859#ifdef NAVIT_SAY_DEBUG_PRINT 1792#ifdef NAVIT_SAY_DEBUG_PRINT
1860 android_send_generic_text(1,"+*#O:exit\n"); 1793 android_send_generic_text(1,"+*#O:exit\n");
1861 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix); 1794 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1898 break; 1831 break;
1899 } 1832 }
1900 if (contains_suffix(n1, suffixes[i].abbrev)) 1833 if (contains_suffix(n1, suffixes[i].abbrev))
1901 { 1834 {
1902 sex = suffixes[i].sex; 1835 sex = suffixes[i].sex;
1903 name1 = replace_suffix(n1, suffixes[i].abbrev, 1836 name1 = replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
1904 suffixes[i].fullname);
1905 break; 1837 break;
1906 } 1838 }
1907 } 1839 }
1908 1840
1909 if (n2) 1841 if (n2)
1937 android_send_generic_text(1,xy); 1869 android_send_generic_text(1,xy);
1938 g_free(xy); 1870 g_free(xy);
1939#endif 1871#endif
1940#endif 1872#endif
1941 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name 1873 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
1942 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, 1874 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, n1, sep, name2);
1943 n1, sep, name2);
1944 break; 1875 break;
1945 case 1: 1876 case 1:
1946#ifdef HAVE_API_ANDROID 1877#ifdef HAVE_API_ANDROID
1947#ifdef NAVIT_SAY_DEBUG_PRINT 1878#ifdef NAVIT_SAY_DEBUG_PRINT
1948 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n"); 1879 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
1959 android_send_generic_text(1,xy); 1890 android_send_generic_text(1,xy);
1960 g_free(xy); 1891 g_free(xy);
1961#endif 1892#endif
1962#endif 1893#endif
1963 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included 1894 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included
1964 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, 1895 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, name1, sep, name2);
1965 name1, sep, name2);
1966 break; 1896 break;
1967 case 2: 1897 case 2:
1968#ifdef HAVE_API_ANDROID 1898#ifdef HAVE_API_ANDROID
1969#ifdef NAVIT_SAY_DEBUG_PRINT 1899#ifdef NAVIT_SAY_DEBUG_PRINT
1970 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n"); 1900 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
1981 android_send_generic_text(1,xy); 1911 android_send_generic_text(1,xy);
1982 g_free(xy); 1912 g_free(xy);
1983#endif 1913#endif
1984#endif 1914#endif
1985 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included 1915 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included
1986 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), 1916 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), prefix, name1, sep, name2);
1987 prefix, name1, sep, name2);
1988 break; 1917 break;
1989 case 3: 1918 case 3:
1990#ifdef HAVE_API_ANDROID 1919#ifdef HAVE_API_ANDROID
1991#ifdef NAVIT_SAY_DEBUG_PRINT 1920#ifdef NAVIT_SAY_DEBUG_PRINT
1992 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n"); 1921 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
2003 android_send_generic_text(1,xy); 1932 android_send_generic_text(1,xy);
2004 g_free(xy); 1933 g_free(xy);
2005#endif 1934#endif
2006#endif 1935#endif
2007 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included 1936 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included
2008 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), 1937 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), prefix, name1, sep, name2);
2009 prefix, name1, sep, name2);
2010 break; 1938 break;
2011 } 1939 }
2012 g_free(name1); 1940 g_free(name1);
2013 1941
2014 } 1942 }
2048 1976
2049 return ret; 1977 return ret;
2050} 1978}
2051 1979
2052static char * 1980static char *
2053show_maneuver(struct navigation *nav, struct navigation_itm *itm, 1981show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
2054 struct navigation_command *cmd, enum attr_type type, int connect)
2055{ 1982{
2056 // TRANSLATORS: right, as in 'Turn right' 1983 // TRANSLATORS: right, as in 'Turn right'
2057 char *dir = _("right"); 1984 char *dir = _("right");
2058 char *strength = ""; 1985 char *strength = "";
2059 int distance = itm->dest_length - cmd->itm->dest_length; 1986 int distance = itm->dest_length - cmd->itm->dest_length;
2189 return g_strdup(_("When possible, please turn around")); 2116 return g_strdup(_("When possible, please turn around"));
2190 } 2117 }
2191 2118
2192 if (!connect) 2119 if (!connect)
2193 { 2120 {
2194 level = navigation_get_announce_level_cmd(nav, itm, cmd, 2121 level = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length);
2195 distance - cmd->length);
2196 } 2122 }
2197 // dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type); 2123 // dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type);
2198 } 2124 }
2199 2125
2200 if (cmd->itm->prev->way.flags & AF_ROUNDABOUT) 2126 if (cmd->itm->prev->way.flags & AF_ROUNDABOUT)
2202 cur = cmd->itm->prev; 2128 cur = cmd->itm->prev;
2203 count_roundabout = 0; 2129 count_roundabout = 0;
2204 while (cur && (cur->way.flags & AF_ROUNDABOUT)) 2130 while (cur && (cur->way.flags & AF_ROUNDABOUT))
2205 { 2131 {
2206 // If the next segment has no exit or the exit isn't allowed, don't count it 2132 // If the next segment has no exit or the exit isn't allowed, don't count it
2207 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 2133 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 3))
2208 3))
2209 { 2134 {
2210 count_roundabout++; 2135 count_roundabout++;
2211 } 2136 }
2212 cur = cur->prev; 2137 cur = cur->prev;
2213 } 2138 }
2247 android_send_generic_text(1,xy); 2172 android_send_generic_text(1,xy);
2248 g_free(xy); 2173 g_free(xy);
2249#endif 2174#endif
2250#endif 2175#endif
2251 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit 2176 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
2252 return g_strdup_printf( 2177 return g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
2253 _("then leave the roundabout at the %s"),
2254 get_exit_count_str(count_roundabout));
2255 case 0: 2178 case 0:
2256#ifdef HAVE_API_ANDROID 2179#ifdef HAVE_API_ANDROID
2257#ifdef NAVIT_SAY_DEBUG_PRINT 2180#ifdef NAVIT_SAY_DEBUG_PRINT
2258 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n"); 2181 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
2259 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout)); 2182 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
2260 android_send_generic_text(1,xy); 2183 android_send_generic_text(1,xy);
2261 g_free(xy); 2184 g_free(xy);
2262#endif 2185#endif
2263#endif 2186#endif
2264 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit 2187 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
2265 return g_strdup_printf(_("Leave the roundabout at the %s"), 2188 return g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
2266 get_exit_count_str(count_roundabout));
2267 } 2189 }
2268 } 2190 }
2269 2191
2270 switch (level) 2192 switch (level)
2271 { 2193 {
2294 break; 2216 break;
2295 case 1: 2217 case 1:
2296 d = get_distance(nav, distance, attr_navigation_short, 0); 2218 d = get_distance(nav, distance, attr_navigation_short, 0);
2297 break; 2219 break;
2298 case 0: 2220 case 0:
2299 skip_roads = count_possible_turns(nav, 2221 skip_roads = count_possible_turns(nav, cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, cmd->delta);
2300 cmd->prev ? cmd->prev->itm : nav->first, cmd->itm,
2301 cmd->delta);
2302 if (skip_roads > 0) 2222 if (skip_roads > 0)
2303 { 2223 {
2304 if (get_count_str(skip_roads + 1)) 2224 if (get_count_str(skip_roads + 1))
2305 { 2225 {
2306#ifdef HAVE_API_ANDROID 2226#ifdef HAVE_API_ANDROID
2313 android_send_generic_text(1,xy); 2233 android_send_generic_text(1,xy);
2314 g_free(xy); 2234 g_free(xy);
2315#endif 2235#endif
2316#endif 2236#endif
2317 // TRANSLATORS: First argument is the how manieth street to take, second the direction 2237 // TRANSLATORS: First argument is the how manieth street to take, second the direction
2318 ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), 2238 ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
2319 get_count_str(skip_roads + 1), dir);
2320 return ret; 2239 return ret;
2321 } 2240 }
2322 else 2241 else
2323 { 2242 {
2324#ifdef HAVE_API_ANDROID 2243#ifdef HAVE_API_ANDROID
2341#endif 2260#endif
2342 d = g_strdup(_("now")); 2261 d = g_strdup(_("now"));
2343 } 2262 }
2344 break; 2263 break;
2345 case -2: 2264 case -2:
2346 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, 2265 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, cmd->delta);
2347 cmd->delta);
2348 if (skip_roads > 0) 2266 if (skip_roads > 0)
2349 { 2267 {
2350 // TRANSLATORS: First argument is the how manieth street to take, second the direction 2268 // TRANSLATORS: First argument is the how manieth street to take, second the direction
2351 // TRANSLATORS: EXAMPLE: ... then take the second road to the right 2269 // TRANSLATORS: EXAMPLE: ... then take the second road to the right
2352 if (get_count_str(skip_roads + 1)) 2270 if (get_count_str(skip_roads + 1))
2360 xy=g_strdup_printf("+*#1:%s\n", dir); 2278 xy=g_strdup_printf("+*#1:%s\n", dir);
2361 android_send_generic_text(1,xy); 2279 android_send_generic_text(1,xy);
2362 g_free(xy); 2280 g_free(xy);
2363#endif 2281#endif
2364#endif 2282#endif
2365 ret = g_strdup_printf( 2283 ret = g_strdup_printf(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
2366 _("then take the %1$s road to the %2$s"),
2367 get_count_str(skip_roads + 1), dir);
2368 return ret; 2284 return ret;
2369 } 2285 }
2370 else 2286 else
2371 { 2287 {
2372#ifdef HAVE_API_ANDROID 2288#ifdef HAVE_API_ANDROID
2458 android_send_generic_text(1,xy); 2374 android_send_generic_text(1,xy);
2459 g_free(xy); 2375 g_free(xy);
2460#endif 2376#endif
2461#endif 2377#endif
2462 // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street' 2378 // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street'
2463 ret = g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, 2379 ret = g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
2464 d, destination ? destination : "");
2465 } 2380 }
2466 else 2381 else
2467 { 2382 {
2468#ifdef HAVE_API_ANDROID 2383#ifdef HAVE_API_ANDROID
2469#ifdef NAVIT_SAY_DEBUG_PRINT 2384#ifdef NAVIT_SAY_DEBUG_PRINT
2481 android_send_generic_text(1,xy); 2396 android_send_generic_text(1,xy);
2482 g_free(xy); 2397 g_free(xy);
2483#endif 2398#endif
2484#endif 2399#endif
2485 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination 2400 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
2486 ret = g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, 2401 ret = g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
2487 dir, d, destination ? destination : "");
2488 } 2402 }
2489 g_free(destination); 2403 g_free(destination);
2490 } 2404 }
2491 else 2405 else
2492 { 2406 {
2524 * immediately following that maneuver, if these are too close and we're in speech navigation. 2438 * immediately following that maneuver, if these are too close and we're in speech navigation.
2525 * 2439 *
2526 * @return An announcement that should be made 2440 * @return An announcement that should be made
2527 */ 2441 */
2528static char * 2442static char *
2529show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, 2443show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
2530 struct navigation_command *cmd, enum attr_type type)
2531{ 2444{
2532 struct navigation_command *cur, *prev; 2445 struct navigation_command *cur, *prev;
2533 int distance = itm->dest_length - cmd->itm->dest_length; 2446 int distance = itm->dest_length - cmd->itm->dest_length;
2534 int level, dist, i, time; 2447 int level, dist, i, time;
2535 int speech_time, time2nav; 2448 int speech_time, time2nav;
2538 if (type != attr_navigation_speech) 2451 if (type != attr_navigation_speech)
2539 { 2452 {
2540 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation 2453 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation
2541 } 2454 }
2542 2455
2543 level = navigation_get_announce_level(nav, itm->way.item.type, 2456 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length);
2544 distance - cmd->length);
2545 2457
2546 if (level > 1) 2458 if (level > 1)
2547 { 2459 {
2548 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close 2460 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close
2549 } 2461 }
2600 old = ret; 2512 old = ret;
2601 buf = show_maneuver(nav, prev->itm, cur, type, 1); 2513 buf = show_maneuver(nav, prev->itm, cur, type, 1);
2602 ret = g_strdup_printf("%s, %s", old, buf); 2514 ret = g_strdup_printf("%s, %s", old, buf);
2603 g_free(buf); 2515 g_free(buf);
2604 2516
2605 if (nav->speech && speech_estimate_duration(nav->speech, ret) 2517 if (nav->speech && speech_estimate_duration(nav->speech, ret) > time2nav)
2606 > time2nav)
2607 { 2518 {
2608 g_free(ret); 2519 g_free(ret);
2609 ret = old; 2520 ret = old;
2610 i = 2; // This will terminate the loop 2521 i = 2; // This will terminate the loop
2611 } 2522 }
2631 } 2542 }
2632 2543
2633 return ret; 2544 return ret;
2634} 2545}
2635 2546
2636static void navigation_call_callbacks(struct navigation *this_, 2547static void navigation_call_callbacks(struct navigation *this_, int force_speech)
2637 int force_speech)
2638{ 2548{
2639 int distance, level = 0; 2549 int distance, level = 0;
2640 void *p = this_; 2550 void *p = this_;
2551
2641 if (!this_->cmd_first) 2552 if (!this_->cmd_first)
2553 {
2642 return; 2554 return;
2555 }
2556
2643 callback_list_call(this_->callback, 1, &p); 2557 callback_list_call(this_->callback, 1, &p);
2644 //dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit); 2558 //dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
2645 distance = round_distance(
2646 this_->first->dest_length - this_->cmd_first->itm->dest_length); 2559 distance = round_distance(this_->first->dest_length - this_->cmd_first->itm->dest_length);
2647 if (this_->turn_around_limit && this_->turn_around 2560 if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit)
2648 == this_->turn_around_limit)
2649 { 2561 {
2650 //dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn); 2562 //dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn);
2651 while (distance > this_->distance_turn) 2563 while (distance > this_->distance_turn)
2652 { 2564 {
2653 this_->level_last = 4; 2565 this_->level_last = 4;
2657 this_->distance_turn *= 2; 2569 this_->distance_turn *= 2;
2658 else 2570 else
2659 this_->distance_turn = 500; 2571 this_->distance_turn = 500;
2660 } 2572 }
2661 } 2573 }
2662 else if (!this_->turn_around_limit || this_->turn_around 2574 else if (!this_->turn_around_limit || this_->turn_around == -this_->turn_around_limit + 1)
2663 == -this_->turn_around_limit + 1)
2664 { 2575 {
2665 this_->distance_turn = 50; 2576 this_->distance_turn = 50;
2666 distance -= this_->cmd_first->length; 2577 distance -= this_->cmd_first->length;
2667 level = navigation_get_announce_level_cmd(this_, this_->first, 2578 level = navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance);
2668 this_->cmd_first, distance);
2669 if (level < this_->level_last) 2579 if (level < this_->level_last)
2670 { 2580 {
2671 /* only tell if the level is valid for more than 3 seconds */ 2581 /* only tell if the level is valid for more than 3 seconds */
2672 int speed_distance = this_->first->speed * 30 / 36; 2582 int speed_distance = this_->first->speed * 30 / 36;
2673 if (distance < speed_distance || navigation_get_announce_level_cmd( 2583 if (distance < speed_distance || navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance - speed_distance) == level)
2674 this_, this_->first, this_->cmd_first,
2675 distance - speed_distance) == level)
2676 { 2584 {
2677 dbg(1, "distance %d speed_distance %d\n", distance, 2585 dbg(1, "distance %d speed_distance %d\n", distance, speed_distance);
2678 speed_distance);
2679 dbg(1, "level %d < %d\n", level, this_->level_last); 2586 dbg(1, "level %d < %d\n", level, this_->level_last);
2680 this_->level_last = level; 2587 this_->level_last = level;
2681 force_speech = 3; 2588 force_speech = 3;
2682 } 2589 }
2683 } 2590 }
2703 2610
2704 if (force_speech) 2611 if (force_speech)
2705 { 2612 {
2706 this_->level_last = level; 2613 this_->level_last = level;
2707 this_->curr_delay = 0; 2614 this_->curr_delay = 0;
2708 dbg(1, "force_speech=%d distance=%d level=%d type=0x%x\n", 2615 dbg(1, "force_speech=%d distance=%d level=%d type=0x%x\n", force_speech, distance, level, this_->first->way.item.type);
2709 force_speech, distance, level, this_->first->way.item.type);
2710 callback_list_call(this_->callback_speech, 1, &p); 2616 callback_list_call(this_->callback_speech, 1, &p);
2711 } 2617 }
2712} 2618}
2713 2619
2714static void navigation_update(struct navigation *this_, struct route *route, 2620static void navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
2715 struct attr *attr)
2716{ 2621{
2717 struct map *map; 2622 struct map *map;
2718 struct map_rect *mr; 2623 struct map_rect *mr;
2719 struct item *ritem; /* Holds an item from the route map */ 2624 struct item *ritem; /* Holds an item from the route map */
2720 struct item *sitem; /* Holds the corresponding item from the actual map */ 2625 struct item *sitem; /* Holds the corresponding item from the actual map */
2724 int mode = 0, incr = 0, first = 1; 2629 int mode = 0, incr = 0, first = 1;
2725 if (attr->type != attr_route_status) 2630 if (attr->type != attr_route_status)
2726 return; 2631 return;
2727 2632
2728 dbg(1, "enter %d\n", mode); 2633 dbg(1, "enter %d\n", mode);
2729 if (attr->u.num == route_status_no_destination || attr->u.num 2634 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
2730 == route_status_not_found || attr->u.num
2731 == route_status_path_done_new)
2732 navigation_flush(this_); 2635 navigation_flush(this_);
2733 if (attr->u.num != route_status_path_done_new && attr->u.num 2636 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
2734 != route_status_path_done_incremental)
2735 return; 2637 return;
2736 2638
2737 if (!this_->route) 2639 if (!this_->route)
2738 return; 2640 return;
2739 map = route_get_map(this_->route); 2641 map = route_get_map(this_->route);
2748 this_->vehicleprofile = NULL; 2650 this_->vehicleprofile = NULL;
2749 //dbg(1,"enter\n"); 2651 //dbg(1,"enter\n");
2750 2652
2751 while ((ritem = map_rect_get_item(mr))) 2653 while ((ritem = map_rect_get_item(mr)))
2752 { 2654 {
2753 if (ritem->type == type_route_start && this_->turn_around 2655 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit + 1)
2754 > -this_->turn_around_limit + 1)
2755 this_->turn_around--; 2656 this_->turn_around--;
2756 if (ritem->type == type_route_start_reverse && this_->turn_around 2657 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
2757 < this_->turn_around_limit)
2758 this_->turn_around++; 2658 this_->turn_around++;
2759 if (ritem->type != type_street_route) 2659 if (ritem->type != type_street_route)
2760 continue; 2660 continue;
2761 2661
2762 if (first && item_attr_get(ritem, attr_street_item, &street_item)) 2662 if (first && item_attr_get(ritem, attr_street_item, &street_item))
2813 callback_list_destroy(this_->callback); 2713 callback_list_destroy(this_->callback);
2814 callback_list_destroy(this_->callback_speech); 2714 callback_list_destroy(this_->callback_speech);
2815 g_free(this_); 2715 g_free(this_);
2816} 2716}
2817 2717
2818int navigation_register_callback(struct navigation *this_, enum attr_type type, 2718int navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
2819 struct callback *cb)
2820{ 2719{
2821 if (type == attr_navigation_speech) 2720 if (type == attr_navigation_speech)
2822 callback_list_add(this_->callback_speech, cb); 2721 callback_list_add(this_->callback_speech, cb);
2823 else 2722 else
2824 callback_list_add(this_->callback, cb); 2723 callback_list_add(this_->callback, cb);
2825 return 1; 2724 return 1;
2826} 2725}
2827 2726
2828void navigation_unregister_callback(struct navigation *this_, 2727void navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
2829 enum attr_type type, struct callback *cb)
2830{ 2728{
2831 if (type == attr_navigation_speech) 2729 if (type == attr_navigation_speech)
2832 callback_list_remove_destroy(this_->callback_speech, cb); 2730 callback_list_remove_destroy(this_->callback_speech, cb);
2833 else 2731 else
2834 callback_list_remove_destroy(this_->callback, cb); 2732 callback_list_remove_destroy(this_->callback, cb);
2879 struct navigation_way *ways; 2777 struct navigation_way *ways;
2880 int show_all; 2778 int show_all;
2881 char *str; 2779 char *str;
2882}; 2780};
2883 2781
2884static int navigation_map_item_coord_get(void *priv_data, struct coord *c, 2782static int navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
2885 int count)
2886{ 2783{
2887 struct map_rect_priv *this = priv_data; 2784 struct map_rect_priv *this = priv_data;
2888 if (this->ccount || !count) 2785 if (this->ccount || !count)
2889 return 0; 2786 return 0;
2890 *c = this->itm->start; 2787 *c = this->itm->start;
2891 this->ccount = 1; 2788 this->ccount = 1;
2892 return 1; 2789 return 1;
2893} 2790}
2894 2791
2895static int navigation_map_item_attr_get(void *priv_data, 2792static int navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2896 enum attr_type attr_type, struct attr *attr)
2897{ 2793{
2898 struct map_rect_priv *this_ = priv_data; 2794 struct map_rect_priv *this_ = priv_data;
2899 struct navigation_command *cmd = this_->cmd; 2795 struct navigation_command *cmd = this_->cmd;
2900 struct navigation_itm *itm = this_->itm; 2796 struct navigation_itm *itm = this_->itm;
2901 struct navigation_itm *prev = itm->prev; 2797 struct navigation_itm *prev = itm->prev;
2916 { 2812 {
2917 case attr_navigation_short: 2813 case attr_navigation_short:
2918 this_->attr_next = attr_navigation_long; 2814 this_->attr_next = attr_navigation_long;
2919 if (cmd) 2815 if (cmd)
2920 { 2816 {
2921 this_->str = attr->u.str = show_next_maneuvers(this_->nav, 2817 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2922 this_->cmd_itm, cmd, attr_type);
2923 return 1; 2818 return 1;
2924 } 2819 }
2925 return 0; 2820 return 0;
2926 case attr_navigation_long: 2821 case attr_navigation_long:
2927 this_->attr_next = attr_navigation_long_exact; 2822 this_->attr_next = attr_navigation_long_exact;
2928 if (cmd) 2823 if (cmd)
2929 { 2824 {
2930 this_->str = attr->u.str = show_next_maneuvers(this_->nav, 2825 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2931 this_->cmd_itm, cmd, attr_type);
2932 return 1; 2826 return 1;
2933 } 2827 }
2934 return 0; 2828 return 0;
2935 case attr_navigation_long_exact: 2829 case attr_navigation_long_exact:
2936 this_->attr_next = attr_navigation_speech; 2830 this_->attr_next = attr_navigation_speech;
2937 if (cmd) 2831 if (cmd)
2938 { 2832 {
2939 this_->str = attr->u.str = show_next_maneuvers(this_->nav, 2833 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2940 this_->cmd_itm, cmd, attr_type);
2941 return 1; 2834 return 1;
2942 } 2835 }
2943 return 0; 2836 return 0;
2944 case attr_navigation_speech: 2837 case attr_navigation_speech:
2945 this_->attr_next = attr_length; 2838 this_->attr_next = attr_length;
2946 if (cmd) 2839 if (cmd)
2947 { 2840 {
2948 this_->str = attr->u.str = show_next_maneuvers(this_->nav, 2841 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
2949 this_->cmd_itm, this_->cmd, attr_type);
2950 return 1; 2842 return 1;
2951 } 2843 }
2952 return 0; 2844 return 0;
2953 case attr_length: 2845 case attr_length:
2954 this_->attr_next = attr_time; 2846 this_->attr_next = attr_time;
2955 if (cmd) 2847 if (cmd)
2956 { 2848 {
2957 attr->u.num = this_->cmd_itm->dest_length 2849 attr->u.num = this_->cmd_itm->dest_length - cmd->itm->dest_length;
2958 - cmd->itm->dest_length;
2959 return 1; 2850 return 1;
2960 } 2851 }
2961 return 0; 2852 return 0;
2962 case attr_time: 2853 case attr_time:
2963 this_->attr_next = attr_destination_length; 2854 this_->attr_next = attr_destination_length;
2990 case attr_debug: 2881 case attr_debug:
2991 switch (this_->debug_idx) 2882 switch (this_->debug_idx)
2992 { 2883 {
2993 case 0: 2884 case 0:
2994 this_->debug_idx++; 2885 this_->debug_idx++;
2995 this_->str = attr->u.str = g_strdup_printf( 2886 this_->str = attr->u.str = g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
2996 "angle:%d (- %d)", itm->way.angle2, itm->angle_end);
2997 return 1; 2887 return 1;
2998 case 1: 2888 case 1:
2999 this_->debug_idx++; 2889 this_->debug_idx++;
3000 this_->str = attr->u.str = g_strdup_printf("item type:%s", 2890 this_->str = attr->u.str = g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
3001 item_to_name(itm->way.item.type));
3002 return 1; 2891 return 1;
3003 case 2: 2892 case 2:
3004 this_->debug_idx++; 2893 this_->debug_idx++;
3005 if (cmd) 2894 if (cmd)
3006 { 2895 {
3007 this_->str = attr->u.str = g_strdup_printf("delta:%d", 2896 this_->str = attr->u.str = g_strdup_printf("delta:%d", cmd->delta);
3008 cmd->delta);
3009 return 1; 2897 return 1;
3010 } 2898 }
3011 case 3: 2899 case 3:
3012 this_->debug_idx++; 2900 this_->debug_idx++;
3013 if (prev) 2901 if (prev)
3014 { 2902 {
3015 this_->str = attr->u.str = g_strdup_printf( 2903 this_->str = attr->u.str = g_strdup_printf("prev street_name:%s", prev->way.name1);
3016 "prev street_name:%s", prev->way.name1);
3017 return 1; 2904 return 1;
3018 } 2905 }
3019 case 4: 2906 case 4:
3020 this_->debug_idx++; 2907 this_->debug_idx++;
3021 if (prev) 2908 if (prev)
3022 { 2909 {
3023 this_->str = attr->u.str = g_strdup_printf( 2910 this_->str = attr->u.str = g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
3024 "prev street_name_systematic:%s",
3025 prev->way.name2);
3026 return 1; 2911 return 1;
3027 } 2912 }
3028 case 5: 2913 case 5:
3029 this_->debug_idx++; 2914 this_->debug_idx++;
3030 if (prev) 2915 if (prev)
3031 { 2916 {
3032 this_->str = attr->u.str = g_strdup_printf( 2917 this_->str = attr->u.str = g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
3033 "prev angle:(%d -) %d", prev->way.angle2,
3034 prev->angle_end);
3035 return 1; 2918 return 1;
3036 } 2919 }
3037 case 6: 2920 case 6:
3038 this_->debug_idx++; 2921 this_->debug_idx++;
3039 this_->ways = itm->way.next; 2922 this_->ways = itm->way.next;
3040 if (prev) 2923 if (prev)
3041 { 2924 {
3042 this_->str = attr->u.str = g_strdup_printf( 2925 this_->str = attr->u.str = g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
3043 "prev item type:%s",
3044 item_to_name(prev->way.item.type));
3045 return 1; 2926 return 1;
3046 } 2927 }
3047 case 7: 2928 case 7:
3048 if (this_->ways && prev) 2929 if (this_->ways && prev)
3049 { 2930 {
3050 this_->str 2931 this_->str = attr->u.str = g_strdup_printf("other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)", this_->ways->angle2, angle_delta(prev->angle_end, this_->ways->angle2), this_->ways->flags, this_->ways->dir, item_to_name(this_->ways->item.type), this_->ways->item.id_hi, this_->ways->item.id_lo);
3051 = attr->u.str
3052 = g_strdup_printf(
3053 "other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)",
3054 this_->ways->angle2,
3055 angle_delta(prev->angle_end,
3056 this_->ways->angle2),
3057 this_->ways->flags,
3058 this_->ways->dir,
3059 item_to_name(
3060 this_->ways->item.type),
3061 this_->ways->item.id_hi,
3062 this_->ways->item.id_lo);
3063 this_->ways = this_->ways->next; 2932 this_->ways = this_->ways->next;
3064 return 1; 2933 return 1;
3065 } 2934 }
3066 this_->debug_idx++; 2935 this_->debug_idx++;
3067 case 8: 2936 case 8:
3068 this_->debug_idx++; 2937 this_->debug_idx++;
3069 if (prev) 2938 if (prev)
3070 { 2939 {
3071 int delta = 0; 2940 int delta = 0;
3072 char *reason = NULL; 2941 char *reason = NULL;
3073 maneuver_required2(this_->nav, prev, itm, &delta, 2942 maneuver_required2(this_->nav, prev, itm, &delta, &reason);
3074 &reason);
3075 this_->str = attr->u.str = g_strdup_printf("reason:%s", 2943 this_->str = attr->u.str = g_strdup_printf("reason:%s", reason);
3076 reason);
3077 return 1; 2944 return 1;
3078 } 2945 }
3079 2946
3080 default: 2947 default:
3081 this_->attr_next = attr_none; 2948 this_->attr_next = attr_none;
3082 return 0; 2949 return 0;
3083 } 2950 }
3084 case attr_any: 2951 case attr_any:
3085 while (this_->attr_next != attr_none) 2952 while (this_->attr_next != attr_none)
3086 { 2953 {
3087 if (navigation_map_item_attr_get(priv_data, this_->attr_next, 2954 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
3088 attr))
3089 return 1; 2955 return 1;
3090 } 2956 }
3091 return 0; 2957 return 0;
3092 default: 2958 default:
3093 attr->type = attr_none; 2959 attr->type = attr_none;
3094 return 0; 2960 return 0;
3095 } 2961 }
3096} 2962}
3097 2963
3098static struct item_methods navigation_map_item_methods = 2964static struct item_methods navigation_map_item_methods = { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
3099{ NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
3100 2965
3101static void navigation_map_destroy(struct map_priv *priv) 2966static void navigation_map_destroy(struct map_priv *priv)
3102{ 2967{
3103 g_free(priv); 2968 g_free(priv);
3104} 2969}
3154 priv->cmd_next = priv->cmd->next; 3019 priv->cmd_next = priv->cmd->next;
3155 if (priv->cmd_itm_next && !priv->cmd_itm_next->next) 3020 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
3156 ret->type = type_nav_destination; 3021 ret->type = type_nav_destination;
3157 else 3022 else
3158 { 3023 {
3159 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags 3024 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & AF_ROUNDABOUT) && (priv->itm->prev->way.flags & AF_ROUNDABOUT))
3160 & AF_ROUNDABOUT) && (priv->itm->prev->way.flags
3161 & AF_ROUNDABOUT))
3162 { 3025 {
3163 enum item_type r = type_none, l = type_none; 3026 enum item_type r = type_none, l = type_none;
3164 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45) 3027 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
3165 { 3028 {
3166 case 0: 3029 case 0:
3252 return ret; 3115 return ret;
3253 } 3116 }
3254 return NULL; 3117 return NULL;
3255} 3118}
3256 3119
3257static struct map_methods navigation_map_meth = 3120static struct map_methods navigation_map_meth = { projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new, navigation_map_rect_destroy, navigation_map_get_item, navigation_map_get_item_byid, NULL, NULL, NULL, };
3258{ projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new,
3259 navigation_map_rect_destroy, navigation_map_get_item,
3260 navigation_map_get_item_byid, NULL, NULL, NULL, };
3261 3121
3262static struct map_priv * 3122static struct map_priv *
3263navigation_map_new(struct map_methods *meth, struct attr **attrs, 3123navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
3264 struct callback_list *cbl)
3265{ 3124{
3266 struct map_priv *ret; 3125 struct map_priv *ret;
3267 struct attr *navigation_attr; 3126 struct attr *navigation_attr;
3268 3127
3269 navigation_attr = attr_search(attrs, NULL, attr_navigation); 3128 navigation_attr = attr_search(attrs, NULL, attr_navigation);
3277 3136
3278void navigation_set_route(struct navigation *this_, struct route *route) 3137void navigation_set_route(struct navigation *this_, struct route *route)
3279{ 3138{
3280 struct attr callback; 3139 struct attr callback;
3281 this_->route = route; 3140 this_->route = route;
3282 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), 3141 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
3283 attr_route_status, this_); 3142 callback_add_names(this_->route_cb, "navigation_set_route", "navigation_update");
3284 callback.type = attr_callback; 3143 callback.type = attr_callback;
3285 callback.u.callback = this_->route_cb; 3144 callback.u.callback = this_->route_cb;
3286 route_add_attr(route, &callback); 3145 route_add_attr(route, &callback);
3287} 3146}
3288 3147

Legend:
Removed from v.28  
changed lines
  Added in v.30

   
Visit the ZANavi Wiki