Fix:maptool:Another name for faroe islands
[navit-package] / navit / navigation.c
index 3e72785..ce01152 100644 (file)
@@ -38,7 +38,7 @@
 #include "plugin.h"
 #include "navit_nls.h"
 
-#define DEBUG
+/* #define DEBUG */
 
 struct suffix {
        char *fullname;
@@ -70,9 +70,9 @@ struct navigation {
        int turn_around;
        int turn_around_limit;
        int distance_turn;
-       int distance_last;
        struct callback *route_cb;
        int announce[route_item_last-route_item_first+1][3];
+       int tell_street_name;
 };
 
 
@@ -123,19 +123,36 @@ angle_opposite(int angle)
        return ((angle+180)%360);
 }
 
+int
+navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
+{
+       dbg(0,"enter %s\n", attr_to_name(type));
+       switch (type) {
+       case attr_map:
+               attr->u.map=this_->map;
+               break;
+       default:
+               return 0;       
+       }
+       attr->type=type;
+       return 1;
+}
+
+
 struct navigation *
 navigation_new(struct attr *parent, struct attr **attrs)
 {
        int i,j;
+       struct attr * attr;
        struct navigation *ret=g_new0(struct navigation, 1);
        ret->hash=item_hash_new();
        ret->callback=callback_list_new();
        ret->callback_speech=callback_list_new();
        ret->level_last=-2;
-       ret->distance_last=-2;
        ret->distance_turn=50;
        ret->turn_around_limit=3;
        ret->navit=parent->u.navit;
+       ret->tell_street_name=1;
 
        for (j = 0 ; j <= route_item_last-route_item_first ; j++) {
                for (i = 0 ; i < 3 ; i++) {
@@ -143,6 +160,10 @@ navigation_new(struct attr *parent, struct attr **attrs)
                }
        }
 
+       if ((attr=attr_search(attrs, NULL, attr_tell_street_name))) {
+               ret->tell_street_name = attr->u.num;
+       }
+
        return ret;     
 }
 
@@ -221,7 +242,7 @@ static char
 {
        switch (n) {
        case 0:
-               return _("zeroth"); // Not shure if this exists, neither if it will ever be needed
+               return _("zeroth"); // Not sure if this exists, neither if it will ever be needed
        case 1:
                return _("first");
        case 2:
@@ -239,6 +260,28 @@ static char
        }
 }
 
+static char
+*get_exit_count_str(int n) 
+{
+       switch (n) {
+       case 0:
+               return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed
+       case 1:
+               return _("first exit");
+       case 2:
+               return _("second exit");
+       case 3:
+               return _("third exit");
+       case 4:
+               return _("fourth exit");
+       case 5:
+               return _("fifth exit");
+       case 6:
+               return _("sixth exit");
+       default: 
+               return NULL;
+       }
+}
 static int
 round_distance(int dist)
 {
@@ -289,7 +332,7 @@ get_distance(int dist, enum attr_type type, int is_length)
                int rem=(dist/100)%10;
                if (rem) {
                        if (is_length)
-                               return g_strdup_printf(_("%d.%d kilometer"), dist/1000, rem);
+                               return g_strdup_printf(_("%d.%d kilometers"), dist/1000, rem);
                        else
                                return g_strdup_printf(_("in %d.%d kilometers"), dist/1000, rem);
                }
@@ -632,7 +675,7 @@ navigation_itm_new(struct navigation *this_, struct item *ritem)
        if (ritem) {
                ret->streetname_told=0;
                if (! item_attr_get(ritem, attr_street_item, &street_item)) {
-                       dbg(0,"no street item\n");
+                       dbg(1, "no street item\n");
                        return NULL;
                }
                if (item_attr_get(ritem, attr_direction, &direction))
@@ -644,7 +687,8 @@ navigation_itm_new(struct navigation *this_, struct item *ritem)
                ret->item=*sitem;
                item_hash_insert(this_->hash, sitem, ret);
                mr=map_rect_new(sitem->map, NULL);
-               sitem=map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo);
+               if (! (sitem=map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
+                       return NULL;
                if (item_attr_get(sitem, attr_street_name, &attr))
                        ret->name1=map_convert_string(sitem->map,attr.u.str);
                if (item_attr_get(sitem, attr_street_name_systematic, &attr))
@@ -969,9 +1013,8 @@ maneuver_required2(struct navigation_itm *old, struct navigation_itm *new, int *
        if (!new->ways) {
                /* No announcement necessary */
                r="no: Only one possibility";
-       } else if (!new->ways->next && new->ways->item.type == type_ramp) {
+       } else if (!new->ways->next && new->ways->item.type == type_ramp && !is_way_allowed(new->ways)) {
                /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
-               /* TODO: check for one way in wrong direction */
                r="no: Only ramp";
        }
        if (! r) {
@@ -1135,23 +1178,26 @@ command_new(struct navigation *this_, struct navigation_itm *itm, int delta)
        dbg(1,"enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
        ret->delta=delta;
        ret->itm=itm;
-       if (itm && itm->prev && itm->prev->ways && !(itm->flags & AF_ROUNDABOUT) && (itm->prev->flags & AF_ROUNDABOUT)) {
+       if (itm && itm->prev && itm->ways && itm->prev->ways && !(itm->flags & AF_ROUNDABOUT) && (itm->prev->flags & AF_ROUNDABOUT)) {
                int len=0;
-               int angle;
+               int angle=0;
                int entry_angle;
                struct navigation_itm *itm2=itm->prev;
                int exit_angle=angle_median(itm->prev->angle_end, itm->ways->angle2);
+               dbg(1,"exit %d median from %d,%d\n", exit_angle,itm->prev->angle_end, itm->ways->angle2);
                while (itm2 && (itm2->flags & AF_ROUNDABOUT)) {
                        len+=itm2->length;
                        angle=itm2->angle_end;
                        itm2=itm2->prev;
                }
-               if (itm2 && itm2->next && itm2->next->next && itm2->ways) {
-                       itm2=itm2->next->next;
+               if (itm2 && itm2->next && itm2->next->ways) {
+                       itm2=itm2->next;
                        entry_angle=angle_median(angle_opposite(itm2->angle_start), itm2->ways->angle2);
+                       dbg(1,"entry %d median from %d(%d),%d\n", entry_angle,angle_opposite(itm2->angle_start), itm2->angle_start, itm2->ways->angle2);
                } else {
                        entry_angle=angle_opposite(angle);
                }
+               dbg(0,"entry %d exit %d\n", entry_angle, exit_angle);
                ret->roundabout_delta=angle_delta(entry_angle, exit_angle);
                ret->length=len;
                
@@ -1278,7 +1324,7 @@ navigation_item_destination(struct navigation_itm *itm, struct navigation_itm *n
                /* TRANSLATORS: gives the name of the next road to turn into (into the E17) */
                ret=g_strdup_printf(_("%sinto the %s"),prefix,itm->name2);
        name1=ret;
-       while (*name1) {
+       while (name1 && *name1) {
                switch (*name1) {
                case '|':
                        *name1='\0';
@@ -1299,7 +1345,7 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat
        /* TRANSLATORS: right, as in 'Turn right' */
        char *dir=_("right"),*strength="";
        int distance=itm->dest_length-cmd->itm->dest_length;
-       char *d,*ret;
+       char *d,*ret=NULL;
        int delta=cmd->delta;
        int level;
        int strength_needed;
@@ -1349,6 +1395,9 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat
                } else if (delta < 165) {
                        /* TRANSLATORS: Don't forget the ending space */
                        strength=_("strongly ");
+               } else if (delta < 180) {
+                       /* TRANSLATORS: Don't forget the ending space */
+                       strength=_("really strongly ");
                } else {
                        dbg(1,"delta=%d\n", delta);
                        /* TRANSLATORS: Don't forget the ending space */
@@ -1388,10 +1437,10 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat
                        }
                        switch (level) {
                        case 0:
-                               ret = g_strdup_printf(_("Leave the roundabout at the %s exit"), get_count_str(count_roundabout));
+                               ret = g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
                                break;
                        case -2:
-                               ret = g_strdup_printf(_("then leave the roundabout at the %s exit"), get_count_str(count_roundabout));
+                               ret = g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
                                break;
                        }
                        return ret;
@@ -1444,7 +1493,7 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat
        }
        if (cmd->itm->next) {
                int tellstreetname = 0;
-               char *destination = NULL; 
+               char *destination = NULL;
  
                if(type == attr_navigation_speech) { // In voice mode
                        // In Voice Mode only tell the street name in level 1 or in level 0 if level 1
@@ -1466,8 +1515,9 @@ show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigat
                else
                     tellstreetname = 1;
 
-               if(tellstreetname) 
+               if(nav->tell_street_name && tellstreetname)
                        destination=navigation_item_destination(cmd->itm, itm, " ");
+
                if (level != -2) {
                        /* 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' */
                        ret=g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination:"");
@@ -1500,7 +1550,7 @@ show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct n
 {
        struct navigation_command *cur,*prev;
        int distance=itm->dest_length-cmd->itm->dest_length;
-       int l0_dist,level,dist,i,time;
+       int level, dist, i, time;
        int speech_time,time2nav;
        char *ret,*old,*buf,*next;
 
@@ -1515,7 +1565,7 @@ show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct n
        }
 
        if (cmd->itm->told) {
-               return "";
+               return g_strdup("");
        }
 
        ret = show_maneuver(nav, itm, cmd, type, 0);
@@ -1620,7 +1670,7 @@ navigation_call_callbacks(struct navigation *this_, int force_speech)
 }
 
 static void
-navigation_update(struct navigation *this_, int mode)
+navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
 {
        struct map *map;
        struct map_rect *mr;
@@ -1628,12 +1678,14 @@ navigation_update(struct navigation *this_, int mode)
        struct item *sitem;                     /* Holds the corresponding item from the actual map */
        struct attr street_item,street_direction;
        struct navigation_itm *itm;
-       int incr=0,first=1;
+       int mode=0, incr=0, first=1;
+       if (attr->type != attr_route_status)
+               return;
 
        dbg(1,"enter %d\n", mode);
-       if (mode < 2 || mode == 4) 
+       if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new) 
                navigation_flush(this_);
-       if (mode < 2)
+       if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
                return;
                
        if (! this_->route)
@@ -1646,6 +1698,10 @@ navigation_update(struct navigation *this_, int mode)
                return;
        dbg(1,"enter\n");
        while ((ritem=map_rect_get_item(mr))) {
+               if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit+1)
+                       this_->turn_around--;
+               if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
+                       this_->turn_around++;
                if (ritem->type != type_street_route)
                        continue;
                if (first && item_attr_get(ritem, attr_street_item, &street_item)) {
@@ -1669,6 +1725,7 @@ navigation_update(struct navigation *this_, int mode)
                }
                navigation_itm_new(this_, ritem);
        }
+       dbg(2,"turn_around=%d\n", this_->turn_around);
        if (first) 
                navigation_destroy_itms_cmds(this_, NULL);
        else {
@@ -1677,17 +1734,6 @@ navigation_update(struct navigation *this_, int mode)
                        make_maneuvers(this_,this_->route);
                }
                calculate_dest_distance(this_, incr);
-               dbg(2,"destination distance old=%d new=%d\n", this_->distance_last, this_->first->dest_length);
-               if (this_->first->dest_length > this_->distance_last && this_->distance_last >= 0) 
-                       this_->turn_around++;
-               else
-                       this_->turn_around--;
-               if (this_->turn_around > this_->turn_around_limit)
-                       this_->turn_around=this_->turn_around_limit;
-               else if (this_->turn_around < -this_->turn_around_limit+1)
-                       this_->turn_around=-this_->turn_around_limit+1;
-               dbg(2,"turn_around=%d\n", this_->turn_around);
-               this_->distance_last=this_->first->dest_length;
                profile(0,"end");
                navigation_call_callbacks(this_, FALSE);
        }
@@ -2104,9 +2150,12 @@ navigation_map_new(struct map_methods *meth, struct attr **attrs)
 void
 navigation_set_route(struct navigation *this_, struct route *route)
 {
+       struct attr callback;
        this_->route=route;
-       this_->route_cb=callback_new_attr_1(callback_cast(navigation_update), attr_route, this_);
-       route_add_callback(route, this_->route_cb);
+       this_->route_cb=callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
+       callback.type=attr_callback;
+       callback.u.callback=this_->route_cb;
+       route_add_attr(route, &callback);
 }
 
 void