diff options
author | mdankov <mdankov@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-04-01 14:23:54 +0000 |
---|---|---|
committer | mdankov <mdankov@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-04-01 14:23:54 +0000 |
commit | ff55efe3007d0b9bc80a8dfac39c4f62a8533962 (patch) | |
tree | 4cd0bb06b36e746cec1129223c3ff700abd580b2 | |
parent | cd7d305b8ade41a12af09397b32366af39f44671 (diff) | |
download | navit-ff55efe3007d0b9bc80a8dfac39c4f62a8533962.tar.gz |
Add:gui_internal:Allow having several waypoints. Fixes #46.|Thanks heiko wegeler.
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@5004 ffa7fe5e-494d-0410-b361-a75ebd5db220
-rw-r--r-- | navit/attr_def.h | 1 | ||||
-rw-r--r-- | navit/bookmarks.c | 13 | ||||
-rw-r--r-- | navit/bookmarks.h | 1 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal.c | 156 | ||||
-rw-r--r-- | navit/navit.c | 101 | ||||
-rw-r--r-- | navit/navit.h | 7 | ||||
-rw-r--r-- | navit/navit_shipped.xml | 4 | ||||
-rw-r--r-- | navit/route.c | 137 | ||||
-rw-r--r-- | navit/route.h | 3 |
9 files changed, 407 insertions, 16 deletions
diff --git a/navit/attr_def.h b/navit/attr_def.h index a01b30aef..44d9697a4 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -234,6 +234,7 @@ ATTR(readwrite) ATTR(cache) ATTR(create) ATTR(persistent) +ATTR(waypoints_flag) /* toggle for "set as destination" to switch between start a new route or add */ ATTR2(0x0002ffff,type_int_end) ATTR2(0x00030000,type_string_begin) ATTR(type) diff --git a/navit/bookmarks.c b/navit/bookmarks.c index 96c6c6721..e70fb6dab 100644 --- a/navit/bookmarks.c +++ b/navit/bookmarks.c @@ -130,6 +130,19 @@ struct item* bookmarks_get_item(struct bookmarks* this_) { return ret; } +int bookmarks_get_bookmark_count(struct bookmarks* this_) { + int ret=0; + bookmarks_item_rewind(this_); + while (this_->current->iter!=NULL) { + struct bookmark_item_priv* data=(struct bookmark_item_priv*)this_->current->iter->data; + if (data->type == type_bookmark) { + ret++; + } + this_->current->iter=g_list_next(this_->current->iter); + } + return ret; +} + const char* bookmarks_item_cwd(struct bookmarks* this_) { return this_->current->label; } diff --git a/navit/bookmarks.h b/navit/bookmarks.h index 5630e5151..d8291289b 100644 --- a/navit/bookmarks.h +++ b/navit/bookmarks.h @@ -45,6 +45,7 @@ void bookmarks_move_up(struct bookmarks *this_); int bookmarks_move_down(struct bookmarks *this_,const char* name); struct item* bookmarks_get_item(struct bookmarks* this_); +int bookmarks_get_bookmark_count(struct bookmarks* this_); void bookmarks_item_rewind(struct bookmarks* this_); const char* bookmarks_item_cwd(struct bookmarks* this_); diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c index 09d9b3de4..e2126912d 100644 --- a/navit/gui/internal/gui_internal.c +++ b/navit/gui/internal/gui_internal.c @@ -2415,6 +2415,111 @@ gui_internal_cmd_delete_bookmark(struct gui_priv *this, struct widget *wm, void } static void +gui_internal_cmd_delete_bookmark_folder(struct gui_priv *this, struct widget *wm, void *data) +{ + struct attr mattr; + GList *l; + navit_get_attr(this->nav, attr_bookmarks, &mattr, NULL); + bookmarks_move_up(mattr.u.bookmarks); + bookmarks_delete_bookmark(mattr.u.bookmarks,wm->prefix); + l=g_list_first(this->root.children); + gui_internal_prune_menu(this, l->data); +} + +static void +gui_internal_cmd_load_bookmarks_as_waypoints(struct gui_priv *this, struct widget *wm, void *data) +{ + struct attr mattr; + + if(navit_get_attr(this->nav, attr_bookmarks, &mattr, NULL) ) { + struct attr attr; + struct item *item; + struct coord c; + struct pcoord *pc; + enum projection pro=bookmarks_get_projection(mattr.u.bookmarks); + int i, bm_count; + + navit_set_destination(this->nav, NULL, NULL, 0); + + bm_count=bookmarks_get_bookmark_count(mattr.u.bookmarks); + pc=g_alloca(bm_count*sizeof(struct pcoord)); + bookmarks_item_rewind(mattr.u.bookmarks); + i=0; + while ((item=bookmarks_get_item(mattr.u.bookmarks))) { + if (!item_attr_get(item, attr_label, &attr)) + continue; + if (item->type == type_bookmark) { + if (item_coord_get(item, &c, 1)) { + pc[i].x=c.x; + pc[i].y=c.y; + pc[i].pro=pro; + i++; + } + } + } + bm_count=i; + + if (bm_count>0){ + navit_set_destinations(this->nav, pc, bm_count, wm->prefix, 1); + if (this->flags & 512) { + struct attr follow; + follow.type=attr_follow; + follow.u.num=180; + navit_set_attr(this->nav, &this->osd_configuration); + navit_set_attr(this->nav, &follow); + navit_zoom_to_route(this->nav, 0); + } + } + } + + gui_internal_prune_menu(this, NULL); +} + +static void +gui_internal_cmd_replace_bookmarks_from_waypoints(struct gui_priv *this, struct widget *wm, void *data) +{ + struct attr mattr; + + if(navit_get_attr(this->nav, attr_bookmarks, &mattr, NULL) ) { + struct attr attr; + char *desc=NULL; + struct pcoord *pc; + int i, bm_count; + + if (bookmarks_get_bookmark_count(mattr.u.bookmarks)>0){ + struct item *item; + bookmarks_item_rewind(mattr.u.bookmarks); + + while ((item=bookmarks_get_item(mattr.u.bookmarks))) { + + if (!item_attr_get(item, attr_label, &attr)) + continue; + + if (item->type == type_bookmark) + bookmarks_delete_bookmark(mattr.u.bookmarks, attr.u.str); + + bookmarks_move_down(mattr.u.bookmarks,wm->prefix); + } + } + bookmarks_item_rewind(mattr.u.bookmarks); + + bm_count=navit_get_destination_count(this->nav); + pc=g_alloca(bm_count*sizeof(struct pcoord)); + navit_get_destinations(this->nav, pc, bm_count); + + for (i=0; i<bm_count; i++){ + desc=g_strdup_printf("%s WP%d", navit_get_destination_description(this->nav, i), i+1); + navit_get_attr(this->nav, attr_bookmarks, &attr, NULL); + bookmarks_add_bookmark(attr.u.bookmarks, &pc[i], desc); + bookmarks_move_down(mattr.u.bookmarks,wm->prefix); + g_free(desc); + } + } + + gui_internal_prune_menu(this, NULL); +} + +static void get_direction(char *buffer, int angle, int mode) { angle=angle%360; @@ -3926,13 +4031,13 @@ gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data) prefix=g_strdup(wm->prefix); } if ( prefix ) - plen=strlen(prefix); + plen=strlen(prefix); gui_internal_prune_menu_count(this, 1, 0); wb=gui_internal_menu(this, _("Bookmarks")); wb->background=this->background; w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); - w->spy=this->spacing*3; + //w->spy=this->spacing*3; gui_internal_widget_append(wb, w); if(navit_get_attr(this->nav, attr_bookmarks, &mattr, NULL) ) { @@ -3960,6 +4065,40 @@ gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data) gui_internal_cmd_bookmarks, NULL); wbm->prefix=g_strdup(".."); gui_internal_widget_append(w, wbm); + + // load bookmark folder as Waypoints, if any + if (bookmarks_get_bookmark_count(mattr.u.bookmarks) > 0){ + wbm=gui_internal_button_new_with_callback(this, _("Bookmarks as Waypoints"), + image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill, + gui_internal_cmd_load_bookmarks_as_waypoints, NULL); + wbm->prefix=g_strdup(prefix); + gui_internal_widget_append(w, wbm); + } + + // save Waypoints in bookmark folder, if route exists + if (navit_get_destination_count(this->nav) > 0){ + if (bookmarks_get_bookmark_count(mattr.u.bookmarks)==0){ + wbm=gui_internal_button_new_with_callback(this, _("Save Waypoints"), + image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill, + gui_internal_cmd_replace_bookmarks_from_waypoints, NULL); + }else{ + wbm=gui_internal_button_new_with_callback(this, _("Replace Waypoints"), + image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill, + gui_internal_cmd_replace_bookmarks_from_waypoints, NULL); + } + wbm->prefix=g_strdup(prefix); + gui_internal_widget_append(w, wbm); + } + + // delete empty folder + if (bookmarks_get_bookmark_count(mattr.u.bookmarks)==0){ + gui_internal_widget_append(w, + wbm=gui_internal_button_new_with_callback(this, _("Delete Folder"), + image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill, + gui_internal_cmd_delete_bookmark_folder, NULL)); + wbm->prefix=g_strdup(prefix); + } + } } @@ -4014,9 +4153,9 @@ gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data) } } } - if (plen) { - g_free(prefix); - } + + g_free(prefix); + if (found) gui_internal_check_exit(this); else @@ -5598,6 +5737,12 @@ gui_internal_cmd2_setting_rules(struct gui_priv *this, char *function, struct at gui_internal_widget_append(w, gui_internal_button_navit_attr_new(this, _("Map follows Vehicle"), gravity_left_center|orientation_horizontal|flags_fill, &on, &off)); + on.u.num=1; + off.u.num=0; + on.type=off.type=attr_waypoints_flag; + gui_internal_widget_append(w, + gui_internal_button_navit_attr_new(this, _("Plan with Waypoints"), gravity_left_center|orientation_horizontal|flags_fill, + &on, &off)); gui_internal_menu_render(this); } @@ -7598,6 +7743,7 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st } + static void gui_internal_cmd2_locale(struct gui_priv *this, char *function, struct attr **in, struct attr ***out, int *valid) { diff --git a/navit/navit.c b/navit/navit.c index 79884c3c0..29f44cdd9 100644 --- a/navit/navit.c +++ b/navit/navit.c @@ -163,6 +163,7 @@ struct navit { /* 2=No gui ok */ int border; int imperial; + int waypoints_flag; struct attr **attr_list; }; @@ -1198,6 +1199,20 @@ navit_cmd_set_destination(struct navit *this, char *function, struct attr **in, static void +navit_cmd_route_remove_next_waypoint(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) +{ + navit_remove_waypoint(this); +} + + +static void +navit_cmd_route_remove_last_waypoint(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) +{ + navit_remove_nth_waypoint(this, navit_get_destination_count(this)-1); +} + + +static void navit_cmd_set_center(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { struct pcoord pc; @@ -1336,6 +1351,8 @@ static struct command_table commands[] = { {"set_center",command_cast(navit_cmd_set_center)}, {"set_center_cursor",command_cast(navit_cmd_set_center_cursor)}, {"set_destination",command_cast(navit_cmd_set_destination)}, + {"route_remove_next_waypoint",command_cast(navit_cmd_route_remove_next_waypoint)}, + {"route_remove_last_waypoint",command_cast(navit_cmd_route_remove_last_waypoint)}, {"set_position",command_cast(navit_cmd_set_position)}, {"announcer_toggle",command_cast(navit_cmd_announcer_toggle)}, {"fmt_coordinates",command_cast(navit_cmd_fmt_coordinates)}, @@ -1511,7 +1528,7 @@ navit_mark_navigation_stopped(char *former_destination_file){ } /** - * Start the route computing to a given set of coordinates + * Start or add a given set of coordinates for route computing * * @param navit The navit instance * @param c The coordinate to start routing to @@ -1536,7 +1553,13 @@ navit_set_destination(struct navit *this_, struct pcoord *c, const char *descrip g_free(destination_file); callback_list_call_attr_0(this_->attr_cbl, attr_destination); if (this_->route) { - route_set_destination(this_->route, c, async); + struct attr attr; + navit_get_attr(this_, attr_waypoints_flag, &attr, NULL); + if (this_->waypoints_flag==0 || route_get_destination_count(this_->route)==0){ + route_set_destination(this_->route, c, async); + }else{ + route_append_destination(this_->route, c, async); + } if (this_->ready == 3) navit_draw(this_); @@ -1573,6 +1596,55 @@ navit_set_destinations(struct navit *this_, struct pcoord *c, int count, const c } } +int +navit_get_destinations(struct navit *this_, struct pcoord *pc, int count) +{ + if(!this_->route) + return 0; + return route_get_destinations(this_->route, pc, count); + +} + +int +navit_get_destination_count(struct navit *this_) +{ + if(!this_->route) + return 0; + return route_get_destination_count(this_->route); +} + +char* +navit_get_destination_description(struct navit *this_, int n) +{ + if(!this_->route) + return NULL; + return route_get_destination_description(this_->route, n); +} + +void +navit_remove_nth_waypoint(struct navit *this_, int n) +{ + if(!this_->route) + return; + if (route_get_destination_count(this_->route)>1){ + route_remove_nth_waypoint(this_->route, n); + }else{ + navit_set_destination(this_, NULL, NULL, 0); + } +} + +void +navit_remove_waypoint(struct navit *this_) +{ + if(!this_->route) + return; + if (route_get_destination_count(this_->route)>1){ + route_remove_waypoint(this_->route); + }else{ + navit_set_destination(this_, NULL, NULL, 0); + } +} + /** * @brief Checks if a route is calculated * @@ -2447,10 +2519,14 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init) attr_updated=(this_->follow_cursor != !!attr->u.num); this_->follow_cursor=!!attr->u.num; break; - case attr_imperial: - attr_updated=(this_->imperial != attr->u.num); - this_->imperial=attr->u.num; - break; + case attr_imperial: + attr_updated=(this_->imperial != attr->u.num); + this_->imperial=attr->u.num; + break; + case attr_waypoints_flag: + attr_updated=(this_->waypoints_flag != !!attr->u.num); + this_->waypoints_flag=!!attr->u.num; + break; default: return 0; } @@ -2638,6 +2714,9 @@ navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, stru case attr_follow_cursor: attr->u.num=this_->follow_cursor; break; + case attr_waypoints_flag: + attr->u.num=this_->waypoints_flag; + break; default: return 0; } @@ -2827,6 +2906,7 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv) int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *); void *attr_object; char *destination_file; + char *description; profile(0,NULL); if (this_->ready != 3) { @@ -2892,12 +2972,19 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv) if (this_->route) { switch(route_destination_reached(this_->route)) { case 1: + description=route_get_destination_description(this_->route, 0); route_remove_waypoint(this_->route); count=route_get_destinations(this_->route, pc, 16); destination_file = bookmarks_get_destination_file(TRUE); - bookmarks_append_coord(this_->former_destination, destination_file, pc, type_former_itinerary_part, NULL, this_->recentdest_count); + bookmarks_append_coord(this_->former_destination, destination_file, pc, type_former_itinerary_part, description, this_->recentdest_count); + g_free(description); break; case 2: + description=route_get_destination_description(this_->route, 0); + count=route_get_destinations(this_->route, pc, 1); + destination_file = bookmarks_get_destination_file(TRUE); + bookmarks_append_coord(this_->former_destination, destination_file, pc, type_former_itinerary_part, description, this_->recentdest_count); + g_free(description); navit_set_destination(this_, NULL, NULL, 0); break; } diff --git a/navit/navit.h b/navit/navit.h index 6bdeafc5a..8ac7a0ff8 100644 --- a/navit/navit.h +++ b/navit/navit.h @@ -50,6 +50,7 @@ struct tracking; struct transformation; struct vehicleprofile; struct command_table; +struct item; void navit_add_mapset(struct navit *this_, struct mapset *ms); struct mapset *navit_get_mapset(struct navit *this_); struct tracking *navit_get_tracking(struct navit *this_); @@ -78,6 +79,12 @@ struct vehicleprofile *navit_get_vehicleprofile(struct navit *this_); GList *navit_get_vehicleprofiles(struct navit *this_); void navit_set_destination(struct navit *this_, struct pcoord *c, const char *description, int async); void navit_set_destinations(struct navit *this_, struct pcoord *c, int count, const char *description, int async); +int navit_get_destinations(struct navit *this_, struct pcoord *pc, int count); +int navit_get_destination_count(struct navit *this_); +char* navit_get_destination_description(struct navit *this_, int n); +void navit_remove_nth_waypoint(struct navit *this_, int n); +void navit_remove_waypoint(struct navit *this_); +char* navit_get_coord_description(struct navit *this_, struct pcoord *c); int navit_check_route(struct navit *this_); struct map* read_former_destinations_from_file(void); void navit_textfile_debug_log(struct navit *this_, const char *fmt, ...); diff --git a/navit/navit_shipped.xml b/navit/navit_shipped.xml index 920e8ecab..cd9001982 100644 --- a/navit/navit_shipped.xml +++ b/navit/navit_shipped.xml @@ -86,6 +86,10 @@ Navigation</text></img> <a name='Route'><text>Route</text> <img src='gui_actions' onclick='route_description()'><text>Description</text></img> <img src='gui_actions' onclick='route_height_profile()'><text>Height Profile</text></img> + <img cond='navit.route.route_status&52' src='gui_stop' onclick='navit.route_remove_last_waypoint()'><text>Drop last +Waypoint</text></img> + <img cond='navit.route.route_status&52' src='gui_stop' onclick='navit.route_remove_next_waypoint()'><text>Drop next +Waypoint</text></img> </a> </html> ]]></gui> diff --git a/navit/route.c b/navit/route.c index fab9e7d17..58171a2d5 100644 --- a/navit/route.c +++ b/navit/route.c @@ -48,6 +48,7 @@ #include <unistd.h> #include <sys/time.h> #endif +#include "navit_nls.h" #include "glib_slice.h" #include "config.h" #include "point.h" @@ -542,8 +543,12 @@ void route_set_profile(struct route *this, struct vehicleprofile *prof) { if (this->vehicleprofile != prof) { - this->vehicleprofile=prof; - route_path_update(this, 1, 1); + this->vehicleprofile = prof; + int dest_count = g_list_length(this->destinations); + struct pcoord *pc; + pc = g_alloca(dest_count*sizeof(struct pcoord)); + route_get_destinations(this, pc, dest_count); + route_set_destinations(this, pc, dest_count, 1); } } @@ -1054,18 +1059,142 @@ route_get_destinations(struct route *this, struct pcoord *pc, int count) } return ret; } - + +/** + * @brief Get the destinations count for the route + * + * @param this The route instance + * @return destination count for the route + */ +int +route_get_destination_count(struct route *this) +{ + return g_list_length(this->destinations); +} + +/** + * @brief Returns a description for a waypoint as (type or street_name_systematic) + (label or WayID[osm_wayid]) + * + * @param this The route instance + * @param n The nth waypoint + * @return The description + */ +char* +route_get_destination_description(struct route *this, int n) +{ + struct route_info *dst; + struct map_rect *mr=NULL; + struct item *item; + struct attr attr; + char *type=NULL; + char *label=NULL; + char *desc=NULL; + + dst=g_list_nth_data(this->destinations,n); + mr=map_rect_new(dst->street->item.map, NULL); + item = map_rect_get_item_byid(mr, dst->street->item.id_hi, dst->street->item.id_lo); + + type=g_strdup(item_to_name(dst->street->item.type)); + + while(item_attr_get(item, attr_any, &attr)) { + if (attr.type==attr_street_name_systematic ){ + g_free(type); + type=attr_to_text(&attr, item->map, 1); + } else if (attr.type==attr_label){ + g_free(label); + label=attr_to_text(&attr, item->map, 1); + } else if (attr.type==attr_osm_wayid && !label){ + char *tmp=attr_to_text(&attr, item->map, 1); + label=g_strdup_printf("WayID %s", tmp); + } + } + + if(!label && !type) { + desc=g_strdup(_("unknown street")); + } else if (!label || strcmp(type, label)==0){ + desc=g_strdup(type); + } else { + desc=g_strdup_printf("%s %s", type, label); + } + + g_free(label); + g_free(type); + + if (mr) + map_rect_destroy(mr); + + return desc; +} + +/** + * @brief Start a route given set of coordinates + * + * @param this The route instance + * @param c The coordinate to start routing to + * @param async 1 for async + * @return nothing + */ void route_set_destination(struct route *this, struct pcoord *dst, int async) { route_set_destinations(this, dst, dst?1:0, async); } +/** + * @brief Append a given set of coordinates for route computing + * + * @param this The route instance + * @param c The coordinate to start routing to + * @param async 1 for async + * @return nothing + */ +void +route_append_destination(struct route *this, struct pcoord *dst, int async) +{ + if (dst){ + struct route_info *dsti; + dsti=route_find_nearest_street(this->vehicleprofile, this->ms, &dst[0]); + if(dsti) { + route_info_distances(dsti, dst->pro); + this->destinations=g_list_append(this->destinations, dsti); + } + /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */ + route_graph_destroy(this->graph); + this->graph=NULL; + this->current_dst=route_get_dst(this); + route_path_update(this, 1, async); + }else{ + route_set_destinations(this, NULL, 0, async); + } +} + +/** + * @brief Remove the nth waypoint of the route + * + * @param this The route instance + * @param n The waypoint to remove + * @return nothing + */ +void +route_remove_nth_waypoint(struct route *this, int n) +{ + struct route_info *ri=g_list_nth_data(this->destinations, n); + this->destinations=g_list_remove(this->destinations,ri); + route_info_free(ri); + /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */ + route_graph_destroy(this->graph); + this->graph=NULL; + this->current_dst=route_get_dst(this); + route_path_update(this, 1, 1); +} + void route_remove_waypoint(struct route *this) { struct route_path *path=this->path2; - this->destinations=g_list_remove(this->destinations,this->destinations->data); + struct route_info *ri=this->destinations->data; + this->destinations=g_list_remove(this->destinations,ri); + route_info_free(ri); this->path2=this->path2->next; route_path_destroy(path,0); if (!this->destinations) diff --git a/navit/route.h b/navit/route.h index c8ff02275..ca2ea3707 100644 --- a/navit/route.h +++ b/navit/route.h @@ -95,8 +95,11 @@ void route_set_position_from_tracking(struct route *this_, struct tracking *trac struct map_selection *route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs); void route_set_destinations(struct route *this_, struct pcoord *dst, int count, int async); int route_get_destinations(struct route *this_, struct pcoord *pc, int count); +int route_get_destination_count(struct route *this_); void route_set_destination(struct route *this_, struct pcoord *dst, int async); +void route_remove_nth_waypoint(struct route *this_, int n); void route_remove_waypoint(struct route *this_); +char* route_get_destination_description(struct route *this_, int n); struct coord route_get_coord_dist(struct route *this_, int dist); struct street_data *street_get_data(struct item *item); struct street_data *street_data_dup(struct street_data *orig); |