Fix:Core:Remove out-ifdefed code, which no longer makes sense, but breaks cscope.
[profile/ivi/navit.git] / navit / navit / navit.c
index f06bc67..99b5da6 100644 (file)
  * Boston, MA  02110-1301, USA.
  */
 
+#define _USE_MATH_DEFINES 1
+#include "config.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
 #include <glib.h>
 #include <math.h>
 #include <time.h>
-#include "config.h"
 #include "debug.h"
 #include "navit.h"
 #include "callback.h"
 #include "profile.h"
 #include "command.h"
 #include "navit_nls.h"
+#include "map.h"
 #include "util.h"
 #include "messages.h"
 #include "vehicleprofile.h"
 #include "sunriset.h"
+#include "bookmarks.h"
+#ifdef HAVE_API_WIN32_BASE
+#include <windows.h>
+#include "util.h"
+#endif
+#ifdef HAVE_API_WIN32_CE
+#include "libc.h"
+#endif
 
 /**
  * @defgroup navit the navit core instance. navit is the object containing nearly everything: A set of maps, one or more vehicle, a graphics object for rendering the map, a gui object for displaying the user interface, a route object, a navigation object and so on. Be warned that it is theoretically possible to have more than one navit object
@@ -90,7 +102,7 @@ struct navit {
        struct layout *layout_current;
        struct graphics *gra;
        struct action *action;
-       struct transformation *trans;
+       struct transformation *trans, *trans_cursor;
        struct compass *compass;
        struct route *route;
        struct navigation *navigation;
@@ -107,11 +119,9 @@ struct navit {
        GList *windows_items;
        struct navit_vehicle *vehicle;
        struct callback_list *attr_cbl;
-       struct callback *nav_speech_cb, *roadbook_callback, *popup_callback, *route_cb;
+       struct callback *nav_speech_cb, *roadbook_callback, *popup_callback, *route_cb, *progress_cb;
        struct datawindow *roadbook_window;
-       struct map *bookmark;
        struct map *former_destination;
-       GHashTable *bookmarks_hash;
        struct point pressed, last, current;
        int button_pressed,moved,popped,zoomed;
        int center_timeout;
@@ -130,7 +140,7 @@ struct navit {
        int drag_bitmap;
        int use_mousewheel;
        struct messagelist *messages;
-       struct callback *resize_callback,*button_callback,*motion_callback;
+       struct callback *resize_callback,*button_callback,*motion_callback,*predraw_callback;
        struct vehicleprofile *vehicleprofile;
        GList *vehicleprofiles;
        int pitch;
@@ -138,11 +148,20 @@ struct navit {
        int prevTs;
        int graphics_flags;
        int zoom_min, zoom_max;
+       int radius;
+       struct bookmarks *bookmarks;
+       int flags;
+                /* 1=No graphics ok */
+                /* 2=No gui ok */
+       int border;
+       int imperial;
+       struct attr **attr_list;
 };
 
 struct gui *main_loop_gui;
 
 struct attr_iter {
+       void *iter;
        union {
                GList *list;
                struct mapset_handle *mapset_handle;
@@ -153,13 +172,15 @@ static void navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv);
 static void navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt);
 static int navit_add_vehicle(struct navit *this_, struct vehicle *v);
 static int navit_set_attr_do(struct navit *this_, struct attr *attr, int init);
-static int navit_get_cursor_pnt(struct navit *this_, struct point *p, int *dir);
+static int navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir);
 static void navit_set_cursors(struct navit *this_);
 static void navit_cmd_zoom_to_route(struct navit *this);
 static void navit_cmd_set_center_cursor(struct navit *this_);
 static void navit_cmd_announcer_toggle(struct navit *this_);
 static void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv);
 
+struct navit *global_navit;
+
 void
 navit_add_mapset(struct navit *this_, struct mapset *ms)
 {
@@ -183,30 +204,48 @@ navit_get_tracking(struct navit *this_)
        return this_->tracking;
 }
 
-static void
+/**
+ * @brief      Get the user data directory.
+ * @param[in]   create - create the directory if it does not exist
+ *
+ * @return     char * to the data directory string.
+ *
+ * returns the directory used to store user data files (center.txt,
+ * destination.txt, bookmark.txt, ...)
+ *
+ */
+char*
+navit_get_user_data_directory(int create) {
+       char *dir;
+       dir = getenv("NAVIT_USER_DATADIR");
+       if (create && !file_exists(dir)) {
+               dbg(0,"creating dir %s\n", dir);
+               if (file_mkdir(dir,0)) {
+                       dbg(0,"failed creating dir %s\n", dir);
+                       return NULL;
+               }
+       }
+       return dir;
+} /* end: navit_get_user_data_directory(gboolean create) */
+
+
+void
 navit_draw_async(struct navit *this_, int async)
 {
-       GList *l;
-       struct navit_vehicle *nv;
 
        if (this_->blocked) {
                this_->blocked |= 2;
                return;
        }
        transform_setup_source_rect(this_->trans);
-       l=this_->vehicles;
-       while (l) {
-               nv=l->data;
-               navit_vehicle_draw(this_, nv, NULL);
-               l=g_list_next(l);
-       }
        graphics_draw(this_->gra, this_->displaylist, this_->mapsets->data, this_->trans, this_->layout_current, async, NULL, this_->graphics_flags|1);
 }
 
 void
 navit_draw(struct navit *this_)
 {
-       navit_draw_async(this_, 0);
+       if (this_->ready == 3)
+               navit_draw_async(this_, 0);
 }
 
 int
@@ -225,6 +264,34 @@ navit_draw_displaylist(struct navit *this_)
 }
 
 static void
+navit_map_progress(struct navit *this_)
+{
+       struct map *map;
+       struct mapset *ms;
+       struct mapset_handle *msh;
+       struct attr attr;
+       struct point p;
+       if (this_->ready != 3)
+               return;
+       p.x=10;
+       p.y=32;
+
+       ms=this_->mapsets->data;
+       msh=mapset_open(ms);
+       while (msh && (map=mapset_next(msh, 0))) {
+               if (map_get_attr(map, attr_progress, &attr, NULL)) {
+                       char *str=g_strdup_printf("%s           ",attr.u.str);
+                       graphics_draw_mode(this_->gra, draw_mode_begin);
+                       graphics_draw_text_std(this_->gra, 16, str, &p);
+                       g_free(str);
+                       p.y+=32;
+                       graphics_draw_mode(this_->gra, draw_mode_end);
+               }
+       }
+       mapset_close(msh);
+}
+
+static void
 navit_redraw_route(struct navit *this_, struct route *route, struct attr *attr)
 {
        int updated;
@@ -250,20 +317,18 @@ navit_handle_resize(struct navit *this_, int w, int h)
        struct map_selection sel;
        int callback=(this_->ready == 1);
        this_->ready |= 2;
-       if (this_->w != w || this_->h != h) {
-               memset(&sel, 0, sizeof(sel));
-               this_->w=w;
-               this_->h=h;
-               sel.u.p_rect.rl.x=w;
-               sel.u.p_rect.rl.y=h;
-               transform_set_screen_selection(this_->trans, &sel);
-               graphics_init(this_->gra);
-               graphics_set_rect(this_->gra, &sel.u.p_rect);
-       }
-       if (this_->ready == 3)
-               navit_draw(this_);
-       if (callback)
+       memset(&sel, 0, sizeof(sel));
+       this_->w=w;
+       this_->h=h;
+       sel.u.p_rect.rl.x=w;
+       sel.u.p_rect.rl.y=h;
+       transform_set_screen_selection(this_->trans, &sel);
+       graphics_init(this_->gra);
+       graphics_set_rect(this_->gra, &sel.u.p_rect);
+       if (callback) 
                callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_);
+       if (this_->ready == 3)
+               navit_draw_async(this_, 1);
 }
 
 static void
@@ -337,7 +402,7 @@ update_transformation(struct transformation *tr, struct point *old, struct point
        transform_set_center(tr, &c);
 }
 
-static void
+void
 navit_set_timeout(struct navit *this_)
 {
        struct attr follow;
@@ -404,6 +469,7 @@ navit_handle_button(struct navit *this_, int pressed, int button, struct point *
                        update_transformation(this_->trans, &this_->pressed, p, NULL);
 #endif
                        graphics_draw_drag(this_->gra, NULL);
+                       transform_copy(this_->trans, this_->trans_cursor);
                        graphics_overlay_disable(this_->gra, 0);
                        if (!this_->zoomed) 
                                navit_set_timeout(this_);
@@ -503,6 +569,20 @@ navit_motion(void *data, struct point *p)
 }
 
 static void
+navit_predraw(struct navit *this_)
+{
+       GList *l;
+       struct navit_vehicle *nv;
+       transform_copy(this_->trans, this_->trans_cursor);
+       l=this_->vehicles;
+       while (l) {
+               nv=l->data;
+               navit_vehicle_draw(this_, nv, NULL);
+               l=g_list_next(l);
+       }
+}
+
+static void
 navit_scale(struct navit *this_, long scale, struct point *p, int draw)
 {
        struct coord c1, c2, *center;
@@ -608,38 +688,641 @@ navit_zoom_out(struct navit *this_, int factor, struct point *p)
        navit_scale(this_, scale, p, 1);
 }
 
-static int
-navit_cmd_zoom_in(struct navit *this_)
+void
+navit_zoom_in_cursor(struct navit *this_, int factor)
 {
        struct point p;
-       if (this_->vehicle && this_->vehicle->follow_curr == 1 && navit_get_cursor_pnt(this_, &p, NULL)) {
-               navit_zoom_in(this_, 2, &p);
+       if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) {
+               navit_zoom_in(this_, factor, &p);
                this_->vehicle->follow_curr=this_->vehicle->follow;
        } else
-               navit_zoom_in(this_, 2, NULL);
-       return 0;
+               navit_zoom_in(this_, factor, NULL);
 }
 
-static int
-navit_cmd_zoom_out(struct navit *this_)
+void
+navit_zoom_out_cursor(struct navit *this_, int factor)
 {
        struct point p;
-       if (this_->vehicle && this_->vehicle->follow_curr == 1 && navit_get_cursor_pnt(this_, &p, NULL)) {
+       if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) {
                navit_zoom_out(this_, 2, &p);
                this_->vehicle->follow_curr=this_->vehicle->follow;
        } else
                navit_zoom_out(this_, 2, NULL);
+}
+
+static int
+navit_cmd_zoom_in(struct navit *this_)
+{
+       navit_zoom_in_cursor(this_, 2);
        return 0;
 }
 
+static int
+navit_cmd_zoom_out(struct navit *this_)
+{
+       navit_zoom_out_cursor(this_, 2);
+       return 0;
+}
+
+
+static void
+navit_cmd_say(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) 
+               navit_say(this, in[0]->u.str);
+}
+
+static GHashTable *cmd_int_var_hash = NULL;
+static GHashTable *cmd_attr_var_hash = NULL;
+
+/**
+ * Store key value pair for the  command system (for int typed values)
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes in[0] is the key string, in[1] is the integer value to store
+ * @param out output attributes, unused 
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_set_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       char*key;
+       struct attr*val;
+       if(!cmd_int_var_hash) {
+               cmd_int_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
+       }
+
+       if ( (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) &&
+            (in && in[1] && ATTR_IS_NUMERIC(in[1]->type))) {
+               val = g_new(struct attr,1);
+               attr_dup_content(in[1],val);
+               key = g_strdup(in[0]->u.str);
+               g_hash_table_insert(cmd_int_var_hash, key, val);
+        }
+}
+
+
+/**
+ * Store key value pair for the  command system (for attr typed values, can be used as opaque handles)
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes in[0] is the key string, in[1] is the attr* value to store
+ * @param out output attributes, unused 
+ * @param valid unused 
+ * @returns nothing
+ */
+//TODO free stored attributes on navit_destroy
+static void
+navit_cmd_set_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       char*key;
+       struct attr*val;
+       if(!cmd_attr_var_hash) {
+               cmd_attr_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
+       }
+
+       if ( (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) &&
+            (in && in[1] )) {
+               val = attr_dup(in[1]);
+               //val = in[1];
+               key = g_strdup(in[0]->u.str);
+               g_hash_table_insert(cmd_attr_var_hash, key, val);
+        }
+}
+
+
+
+/**
+ * command to toggle the active state of a named layer of the current layout
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] is the name of the layer
+ * @param out output unused
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_toggle_layer(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
+               if(this->layout_current && this->layout_current->layers) {
+                       GList* layers = this->layout_current->layers;
+                       while (layers) {
+                               struct layer*l=layers->data;
+                               if(l && !strcmp(l->name,in[0]->u.str) ) {
+                                       l->active ^= 1;
+                                       navit_draw(this);
+                                       return;
+                               }
+                               layers=g_list_next(layers);
+                       }
+               }
+        }
+}
+
+/**
+ * adds an item with the current coordinate of the vehicle to a named map
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] is the name of the map 
+ * @param out output attribute, 0 on error or the id of the created item on success
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_map_add_curr_pos(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr **list = g_new0(struct attr *,2);
+       struct attr*val = g_new0(struct attr,1);
+       struct mapset* ms;
+       struct map_selection sel;
+       const int selection_range = 10;
+       enum item_type item_type;
+       struct item *it;
+       struct map* curr_map = NULL;
+       struct coord curr_coord;
+       struct map_rect *mr;
+       
+       //return invalid item on error
+       val->type   = attr_none;
+       val->u.item  = NULL;    
+       list[0]     = val;
+       list[1]     = NULL;
+       *out = list;
+       if (
+               in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str && //map name
+                     in[1] && ATTR_IS_STRING(in[1]->type) && in[1]->u.str    //item type
+       ) {
+
+               if(!(ms=navit_get_mapset(this))) {
+                       return;
+               }
+
+               if((item_type = item_from_name(in[1]->u.str))==type_none) {
+                       return;
+               }
+
+               curr_map = mapset_get_map_by_name(ms, in[0]->u.str);
+
+               //no map with the given name found
+               if( ! curr_map) {
+                       return;
+               }
+       
+               if(this->vehicle && this->vehicle->vehicle ) {
+                       struct attr pos_attr;
+                       if(vehicle_get_attr(this->vehicle->vehicle,attr_position_coord_geo,&pos_attr,NULL)) {
+                               transform_from_geo(projection_mg, pos_attr.u.coord_geo, &curr_coord);
+                       } else {
+                               return;
+                       }
+               } else {
+                       return;
+               }
+
+               sel.next=NULL;
+               sel.order=18;
+               sel.range.min=type_none;
+               sel.range.max=type_tec_common;
+               sel.u.c_rect.lu.x=curr_coord.x-selection_range;
+               sel.u.c_rect.lu.y=curr_coord.y+selection_range;
+               sel.u.c_rect.rl.x=curr_coord.x+selection_range;
+               sel.u.c_rect.rl.y=curr_coord.y-selection_range;
+               mr = map_rect_new(curr_map, &sel);
+               if(mr) {
+                       it = map_rect_create_item( mr, item_type);
+                       if (it) {
+                               val->type = attr_type_item_begin;
+                               item_coord_set(it,&curr_coord, 1, change_mode_modify);
+                       }
+                       val->u.item  = it;
+               }
+               map_rect_destroy(mr);
+        }
+}
+
+/**
+ * sets an attribute (name value pair) of a map item specified by map name and item id
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] - name of the map  ; in[1] - item  ; in[2] - attr name ; in[3] - attr value
+ * @param out output attribute, 0 on error, 1 on success
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_map_item_set_attr(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       if (
+               in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str  &&//map name
+                     in[1] && ATTR_IS_ITEM(in[1]->type)   &&                  //item
+                     in[2] && ATTR_IS_STRING(in[2]->type) && in[2]->u.str && //attr_type str
+                     in[3] && ATTR_IS_STRING(in[3]->type) && in[3]->u.str    //attr_value str
+       ) {
+               struct attr attr_to_set;
+               struct map* curr_map = NULL;
+               struct mapset *ms;
+               struct map_selection sel;
+               const int selection_range = 500;
+               struct coord curr_coord;
+               struct item *it;
+               
+               if(ATTR_IS_STRING(attr_from_name(in[2]->u.str))) {
+                       attr_to_set.u.str = in[3]->u.str;
+                       attr_to_set.type = attr_from_name(in[2]->u.str);
+               }
+               else if(ATTR_IS_INT(attr_from_name(in[2]->u.str))) {
+                       attr_to_set.u.num = atoi(in[3]->u.str);
+                       attr_to_set.type = attr_from_name(in[2]->u.str);
+               }
+               else if(ATTR_IS_DOUBLE(attr_from_name(in[2]->u.str))) {
+                       double* val = g_new0(double,1);
+                       *val = atof(in[3]->u.str);
+                       attr_to_set.u.numd = val;
+                       attr_to_set.type = attr_from_name(in[2]->u.str);
+               }
+
+               ms = navit_get_mapset(this);
+
+               curr_map = mapset_get_map_by_name(ms, in[0]->u.str);
+
+               if( ! curr_map) {
+                       return;
+               }
+               sel.next=NULL;
+               sel.order=18;
+               sel.range.min=type_none;
+               sel.range.max=type_tec_common;
+               sel.u.c_rect.lu.x=curr_coord.x-selection_range;
+               sel.u.c_rect.lu.y=curr_coord.y+selection_range;
+               sel.u.c_rect.rl.x=curr_coord.x+selection_range;
+               sel.u.c_rect.rl.y=curr_coord.y-selection_range;
+               it = in[1]->u.item;
+               if(it) {
+                       item_attr_set(it, &attr_to_set, change_mode_modify);
+               }
+       }
+}
+
+/**
+ * Get attr variable given a key string for the command system (for opaque usage)
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] is the key string
+ * @param out output attribute, the attr for the given key string if exists or NULL  
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_get_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr **list = g_new0(struct attr *,2);
+       if(!cmd_int_var_hash) {
+               struct attr*val = g_new0(struct attr,1);
+               cmd_attr_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
+               val->type   = attr_type_item_begin;
+               val->u.item = NULL;
+               list[0]     = val;
+       }
+       if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
+               struct attr*ret = g_hash_table_lookup(cmd_attr_var_hash, in[0]->u.str);
+                if(ret) {
+                       list[0] = attr_dup(ret);
+               }
+               else {
+                       struct attr*val = g_new0(struct attr,1);
+                       val->type   = attr_type_int_begin;
+                       val->u.item = NULL;
+                       list[0]   = val;
+               }
+        }
+       list[1] = NULL;
+       *out = list;
+}
+
+
+/**
+ * Get value given a key string for the command system
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] is the key string
+ * @param out output attribute, the value for the given key string if exists or 0  
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_get_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr **list = g_new0(struct attr *,2);
+       if(!cmd_int_var_hash) {
+               struct attr*val = g_new0(struct attr,1);
+               cmd_int_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
+               val->type   = attr_type_int_begin;
+               val->u.num  = 0;
+               list[0]     = val;
+       }
+       if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
+               struct attr*ret = g_hash_table_lookup(cmd_int_var_hash, in[0]->u.str);
+                if(ret) {
+                       list[0] = attr_dup(ret);
+               }
+               else {
+                       struct attr*val = g_new0(struct attr,1);
+                       val->type   = attr_type_int_begin;
+                       val->u.num  = 0;
+                       list[0]   = val;
+               }
+        }
+       list[1] = NULL;
+       *out = list;
+}
+
+GList *cmd_int_var_stack = NULL;
+
+/**
+ * Push an integer to the stack for the command system
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attribute in[0] is the integer attibute to push
+ * @param out output attributes, unused 
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_push_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       if (in && in[0] && ATTR_IS_NUMERIC(in[0]->type)) {
+               struct attr*val = g_new(struct attr,1);
+               attr_dup_content(in[0],val);
+               cmd_int_var_stack = g_list_prepend(cmd_int_var_stack, val);
+       }
+}
+
+/**
+ * Pop an integer from the command system's integer stack
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes unused
+ * @param out output attribute, the value popped if stack isn't empty or 0
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_pop_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr **list = g_new0(struct attr *,2);
+       if(!cmd_int_var_stack) {
+               struct attr*val = g_new0(struct attr,1);
+               val->type = attr_type_int_begin;
+               val->u.num  = 0;
+               list[0]   = val;
+       }
+       else {
+               list[0] = cmd_int_var_stack->data;
+               cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack,cmd_int_var_stack);
+       }
+       list[1] = NULL;
+       *out = list;
+}
+
+/**
+ * Get current size of command system's integer stack
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes unused
+ * @param out output attribute, the size of stack
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_int_stack_size(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr **list;
+       struct attr *attr  = g_new0(struct attr  ,1);
+       attr->type  = attr_type_int_begin;
+       if(!cmd_int_var_stack) {
+               attr->u.num = 0; 
+       }
+       else {
+               attr->u.num = g_list_length(cmd_int_var_stack); 
+       }
+       list = g_new0(struct attr *,2);
+       list[0] = attr;
+       list[1] = NULL;
+       *out = list;
+       cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack,cmd_int_var_stack);
+}
+
+static struct attr **
+navit_get_coord(struct navit *this, struct attr **in, struct pcoord *pc)
+{
+       if (!in)
+               return NULL;
+       if (!in[0])
+               return NULL;
+       pc->pro = transform_get_projection(this->trans);
+       if (ATTR_IS_STRING(in[0]->type)) {
+               struct coord c;
+               coord_parse(in[0]->u.str, pc->pro, &c);
+               pc->x=c.x;
+               pc->y=c.y;
+               in++;   
+       } else if (ATTR_IS_COORD(in[0]->type)) {
+               pc->x=in[0]->u.coord->x;
+               pc->y=in[0]->u.coord->y;
+               in++;
+       } else if (ATTR_IS_PCOORD(in[0]->type)) {
+               *pc=*in[0]->u.pcoord;
+               in++;
+       } else if (in[1] && in[2] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type) && ATTR_IS_INT(in[2]->type)) {
+               pc->pro=in[0]->u.num;
+               pc->x=in[1]->u.num;
+               pc->y=in[2]->u.num;
+               in+=3;
+       } else if (in[1] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type)) {
+               pc->x=in[0]->u.num;
+               pc->y=in[1]->u.num;
+               in+=2;
+       } else
+               return NULL;
+       return in;
+}
+
+static void
+navit_cmd_set_destination(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct pcoord pc;
+       char *description=NULL;
+       in=navit_get_coord(this, in, &pc);
+       if (!in)
+               return;
+       if (in[0] && ATTR_IS_STRING(in[0]->type))
+               description=in[0]->u.str;
+       navit_set_destination(this, &pc, description, 1);
+}
+
+
+static void
+navit_cmd_set_center(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct pcoord pc;
+       in=navit_get_coord(this, in, &pc);
+       if (!in)
+               return;
+       navit_set_center(this, &pc, 0);
+}
+
+static void
+navit_cmd_fmt_coordinates(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr attr;
+       attr.type=attr_type_string_begin;
+       attr.u.str="Fix me";
+       if (out) {
+               *out=attr_generic_add_attr(*out, &attr);
+       }
+}
+
+/**
+ * Join several string attributes into one
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes in[0] - separator, in[1..] - attributes to join
+ * @param out output attribute joined attribute as string
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_strjoin(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       struct attr attr;
+       gchar *ret, *sep;
+       int i;
+       attr.type=attr_type_string_begin;
+       attr.u.str=NULL;
+       if(in[0] && in[1]) {
+               sep=attr_to_text(in[0],NULL,1);
+               ret=attr_to_text(in[1],NULL,1);
+               for(i=2;in[i];i++) {
+                       gchar *in_i=attr_to_text(in[i],NULL,1);
+                       gchar *r=g_strjoin(sep,ret,in_i,NULL);
+                       g_free(in_i);
+                       g_free(ret);
+                       ret=r;
+               }
+               g_free(sep);
+               attr.u.str=ret;
+               if(out) {
+                       *out=attr_generic_add_attr(*out, &attr);
+               }
+               g_free(ret);
+       }
+}
+
+/**
+ * Call external program
+ *
+ * @param navit The navit instance
+ * @param function unused (needed to match command function signiture)
+ * @param in input attributes in[0] - name of executable, in[1..] - parameters
+ * @param out output attribute unused
+ * @param valid unused 
+ * @returns nothing
+ */
+static void
+navit_cmd_spawn(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+       int i,j, nparms, nvalid;
+       const char ** argv=NULL;
+       struct spawn_process_info *pi;
+
+       nparms=0;
+       nvalid=0;
+       if(in) {
+               while(in[nparms]) {
+                       if (in[nparms]->type!=attr_none) 
+                               nvalid++;
+                       nparms++;
+               }
+       }
+       
+       if(nvalid>0) {
+               argv=g_new(char*,nvalid+1);
+               for(i=0,j=0;in[i];i++) {
+                       if(in[i]->type!=attr_none ) {
+                               argv[j++]=attr_to_text(in[i],NULL,1);
+                       } else {
+                               dbg(0,"Parameter #%i is attr_none - skipping\n",i);
+                       }
+               }
+               argv[j]=NULL;
+               pi=spawn_process(argv);
+               
+               // spawn_process() testing suite - uncomment following code to test.
+               //sleep(3);
+               // example of non-blocking wait
+               //int st=spawn_process_check_status(pi,0);dbg(0,"status %i\n",st);
+               // example of blocking wait
+               //st=spawn_process_check_status(pi,1);dbg(0,"status %i\n",st);
+               // example of wait after process is finished and status is
+               // already tested
+               //st=spawn_process_check_status(pi,1);dbg(0,"status %i\n",st);
+               // example of wait after process is finished and status is
+               // already tested - unblocked
+               //st=spawn_process_check_status(pi,0);dbg(0,"status %i\n",st);
+               
+               // End testing suite
+               spawn_process_info_free(pi);
+               for(i=0;argv[i];i++)
+                       g_free(argv[i]);
+               g_free(argv);
+       }
+}
+
+
 static struct command_table commands[] = {
        {"zoom_in",command_cast(navit_cmd_zoom_in)},
        {"zoom_out",command_cast(navit_cmd_zoom_out)},
        {"zoom_to_route",command_cast(navit_cmd_zoom_to_route)},
+       {"say",command_cast(navit_cmd_say)},
+       {"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)},
        {"announcer_toggle",command_cast(navit_cmd_announcer_toggle)},
+       {"fmt_coordinates",command_cast(navit_cmd_fmt_coordinates)},
+       {"set_int_var",command_cast(navit_cmd_set_int_var)},
+       {"get_int_var",command_cast(navit_cmd_get_int_var)},
+       {"push_int",command_cast(navit_cmd_push_int)},
+       {"pop_int",command_cast(navit_cmd_pop_int)},
+       {"int_stack_size",command_cast(navit_cmd_int_stack_size)},
+       {"toggle_layer",command_cast(navit_cmd_toggle_layer)},
+       {"strjoin",command_cast(navit_cmd_strjoin)},
+       {"spawn",command_cast(navit_cmd_spawn)},
+       {"map_add_curr_pos",command_cast(navit_cmd_map_add_curr_pos)},
+       {"map_item_set_attr",command_cast(navit_cmd_map_item_set_attr)},
+       {"set_attr_var",command_cast(navit_cmd_set_attr_var)},
+       {"get_attr_var",command_cast(navit_cmd_get_attr_var)},
 };
        
+void 
+navit_command_add_table(struct navit*this_, struct command_table *commands, int count)
+{
+  command_add_table(this_->attr_cbl, commands, count, this_);
+}
 
 struct navit *
 navit_new(struct attr *parent, struct attr **attrs)
@@ -657,8 +1340,6 @@ navit_new(struct attr *parent, struct attr **attrs)
        this_->self.u.navit=this_;
        this_->attr_cbl=callback_list_new();
 
-       this_->bookmarks_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
        this_->orientation=-1;
        this_->tracking_flag=1;
        this_->recentdest_count=10;
@@ -672,16 +1353,22 @@ navit_new(struct attr *parent, struct attr **attrs)
        this_->zoom_min = 1;
        this_->zoom_max = 2097152;
        this_->follow_cursor = 1;
+       this_->radius = 30;
+       this_->border = 16;
 
        this_->trans = transform_new();
+       this_->trans_cursor = transform_new();
        transform_from_geo(pro, &g, &co);
        center.x=co.x;
        center.y=co.y;
        center.pro = pro;
        
+       transform_setup(this_->trans, &center, zoom, (this_->orientation != -1) ? this_->orientation : 0);
+
+       this_->bookmarks=bookmarks_new(&this_->self, NULL, this_->trans);
+
        this_->prevTs=0;
 
-       transform_setup(this_->trans, &center, zoom, (this_->orientation != -1) ? this_->orientation : 0);
        for (;*attrs; attrs++) {
                navit_set_attr_do(this_, *attrs, 1);
        }
@@ -702,271 +1389,75 @@ navit_set_gui(struct navit *this_, struct gui *gui)
        if (gui_has_main_loop(this_->gui)) {
                if (! main_loop_gui) {
                        main_loop_gui=this_->gui;
-               } else {
-                       dbg(0,"gui with main loop already active, ignoring this instance");
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-void 
-navit_add_message(struct navit *this_, char *message)
-{
-       message_new(this_->messages, message);
-}
-
-struct message
-*navit_get_messages(struct navit *this_)
-{
-       return message_get(this_->messages);
-}
-
-static int
-navit_set_graphics(struct navit *this_, struct graphics *gra)
-{
-       if (this_->gra)
-               return 0;
-       this_->gra=gra;
-       this_->resize_callback=callback_new_attr_1(callback_cast(navit_resize), attr_resize, this_);
-       graphics_add_callback(gra, this_->resize_callback);
-       this_->button_callback=callback_new_attr_1(callback_cast(navit_button), attr_button, this_);
-       graphics_add_callback(gra, this_->button_callback);
-       this_->motion_callback=callback_new_attr_1(callback_cast(navit_motion), attr_motion, this_);
-       graphics_add_callback(gra, this_->motion_callback);
-       return 1;
-}
-
-struct graphics *
-navit_get_graphics(struct navit *this_)
-{
-       return this_->gra;
-}
-
-struct vehicleprofile *
-navit_get_vehicleprofile(struct navit *this_)
-{
-       return this_->vehicleprofile;
-}
-
-GList *
-navit_get_vehicleprofiles(struct navit *this_)
-{
-       return this_->vehicleprofiles;
-}
-
-static void
-navit_projection_set(struct navit *this_, enum projection pro)
-{
-       struct coord_geo g;
-       struct coord *c;
-
-       c=transform_center(this_->trans);
-       transform_to_geo(transform_get_projection(this_->trans), c, &g);
-       transform_set_projection(this_->trans, pro);
-       transform_from_geo(pro, &g, c);
-       navit_draw(this_);
-}
-
-/**
- * @param limit Limits the number of entries in the "backlog". Set to 0 for "infinite"
- */
-static void
-navit_append_coord(struct navit *this_, char *file, struct pcoord *c, const char *type, const char *description, GHashTable *h, int limit)
-{
-       FILE *f;
-       int offset=0;
-       char *buffer;
-       int ch,prev,lines=0;
-       int numc,readc;
-       int fd;
-       const char *prostr;
-
-       f=fopen(file, "r");
-       if (!f)
-               goto new_file;
-       if (limit != 0) {
-               prev = '\n';
-               while ((ch = fgetc(f)) != EOF) {
-                       if ((ch == '\n') && (prev != '\n')) {
-                               lines++;
-                       }
-                       prev = ch;
-               }
-
-               if (prev != '\n') { // Last line did not end with a newline
-                       lines++;
-               }
-
-               fclose(f);
-               f = fopen(file, "r+");
-               fd = fileno(f);
-               while (lines >= limit) { // We have to "scroll up"
-                       rewind(f);
-                       numc = 0; // Counts how many bytes we have in our line to scroll up
-                       while ((ch = fgetc(f)) != EOF) {
-                               numc++;
-                               if (ch == '\n') {
-                                       break;
-                               }
-                       }
-
-                       buffer=g_malloc(numc);
-                       offset = numc; // Offset holds where we currently are
-                       
-                       do {
-                               fseek(f,offset,SEEK_SET);
-                               readc = fread(buffer,1,numc,f);
-                               
-                               fseek(f,-(numc+readc),SEEK_CUR);
-                               fwrite(buffer,1,readc,f);
-
-                               offset += readc;
-                       } while (readc == numc);
-
-                       g_free(buffer);
-                       fflush(f);
-                       ftruncate(fd,(offset-numc));
-#ifdef HAVE_FSYNC
-                       fsync(fd);
-#endif
-
-                       lines--;
-               }
-               fclose(f);
-       }
-
-new_file:
-       f=fopen(file, "a");
-       if (f) {
-               if (c) {
-                       prostr = projection_to_name(c->pro,NULL);
-                       fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\"\n",
-                                prostr, *prostr ? ":" : "", 
-                                c->x >= 0 ? "":"-", c->x >= 0 ? c->x : -c->x, 
-                                c->y >= 0 ? "":"-", c->y >= 0 ? c->y : -c->y, 
-                                type, description);
-               } else
-                       fprintf(f,"\n");
-       }
-       fclose(f);
-}
-
-/*
- * navit_get_user_data_directory
- * 
- * returns the directory used to store user data files (center.txt,
- * destination.txt, bookmark.txt, ...)
- *
- * arg: gboolean create: create the directory if it does not exist
- */
-static char*
-navit_get_user_data_directory(gboolean create) {
-       char *dir;
-       dir = getenv("NAVIT_USER_DATADIR");
-       if (create && !file_exists(dir)) {
-               dbg(0,"creating dir %s\n", dir);
-               if (file_mkdir(dir,0)) {
-                       dbg(0,"failed creating dir %s\n", dir);
-                       return NULL;
+               } else {
+                       dbg(0,"gui with main loop already active, ignoring this instance");
+                       return 0;
                }
        }
-
-       return dir;
+       return 1;
 }
 
-/*
- * navit_get_destination_file
- * 
- * returns the name of the file used to store destinations with its
- * full path
- *
- * arg: gboolean create: create the directory where the file is stored
- * if it does not exist
- */
-static char*
-navit_get_destination_file(gboolean create)
+void 
+navit_add_message(struct navit *this_, char *message)
 {
-       return g_strjoin(NULL, navit_get_user_data_directory(create), "/destination.txt", NULL);
+       message_new(this_->messages, message);
 }
 
-/*
- * navit_get_bookmark_file
- * 
- * returns the name of the file used to store bookmarks with its
- * full path
- *
- * arg: gboolean create: create the directory where the file is stored
- * if it does not exist
- */
-static char*
-navit_get_bookmark_file(gboolean create)
+struct message
+*navit_get_messages(struct navit *this_)
 {
-       return g_strjoin(NULL, navit_get_user_data_directory(create), "/bookmark.txt", NULL);
+       return message_get(this_->messages);
 }
 
-
-/*
- * navit_get_bookmark_file
- * 
- * returns the name of the file used to store the center file  with its
- * full path
- *
- * arg: gboolean create: create the directory where the file is stored
- * if it does not exist
- */
-static char*
-navit_get_center_file(gboolean create)
+static int
+navit_set_graphics(struct navit *this_, struct graphics *gra)
 {
-       return g_strjoin(NULL, navit_get_user_data_directory(create), "/center.txt", NULL);
+       if (this_->gra)
+               return 0;
+       this_->gra=gra;
+       this_->resize_callback=callback_new_attr_1(callback_cast(navit_resize), attr_resize, this_);
+       graphics_add_callback(gra, this_->resize_callback);
+       this_->button_callback=callback_new_attr_1(callback_cast(navit_button), attr_button, this_);
+       graphics_add_callback(gra, this_->button_callback);
+       this_->motion_callback=callback_new_attr_1(callback_cast(navit_motion), attr_motion, this_);
+       graphics_add_callback(gra, this_->motion_callback);
+       this_->predraw_callback=callback_new_attr_1(callback_cast(navit_predraw), attr_predraw, this_);
+       graphics_add_callback(gra, this_->predraw_callback);
+       return 1;
 }
 
-static void
-navit_set_center_from_file(struct navit *this_, char *file)
+struct graphics *
+navit_get_graphics(struct navit *this_)
 {
-#ifndef HAVE_API_ANDROID
-       FILE *f;
-       char *line = NULL;
+       return this_->gra;
+}
 
-       size_t line_size = 0;
-       enum projection pro;
-       struct coord *center;
+struct vehicleprofile *
+navit_get_vehicleprofile(struct navit *this_)
+{
+       return this_->vehicleprofile;
+}
 
-       f = fopen(file, "r");
-       if (! f)
-               return;
-       getline(&line, &line_size, f);
-       fclose(f);
-       if (line) {
-               center = transform_center(this_->trans);
-               pro = transform_get_projection(this_->trans);
-               coord_parse(g_strchomp(line), pro, center);
-               free(line);
-       }
-       return;
-#endif
+GList *
+navit_get_vehicleprofiles(struct navit *this_)
+{
+       return this_->vehicleprofiles;
 }
+
 static void
-navit_write_center_to_file(struct navit *this_, char *file)
+navit_projection_set(struct navit *this_, enum projection pro, int draw)
 {
-       FILE *f;
-       enum projection pro;
-       struct coord *center;
+       struct coord_geo g;
+       struct coord *c;
 
-       f = fopen(file, "w+");
-       if (f) {
-               center = transform_center(this_->trans);
-               pro = transform_get_projection(this_->trans);
-               coord_print(pro, center, f);
-               fclose(f);
-       } else {
-               perror(file);
-       }
-       return;
+       c=transform_center(this_->trans);
+       transform_to_geo(transform_get_projection(this_->trans), c, &g);
+       transform_set_projection(this_->trans, pro);
+       transform_from_geo(pro, &g, c);
+       if (draw)
+               navit_draw(this_);
 }
 
-
 /**
  * Start the route computing to a given set of coordinates
  *
@@ -978,14 +1469,17 @@ navit_write_center_to_file(struct navit *this_, char *file)
 void
 navit_set_destination(struct navit *this_, struct pcoord *c, const char *description, int async)
 {
+       char *destination_file;
        if (c) {
                this_->destination=*c;
                this_->destination_valid=1;
+
+               dbg(1, "c=(%i,%i)\n", c->x,c->y);
+               destination_file = bookmarks_get_destination_file(TRUE);
+               bookmarks_append_coord(this_->former_destination, destination_file, c, type_former_destination, description, this_->recentdest_count);
+               g_free(destination_file);
        } else
                this_->destination_valid=0;
-       char *destination_file = navit_get_destination_file(TRUE);
-       navit_append_coord(this_, destination_file, c, "former_destination", description, NULL, this_->recentdest_count);
-       g_free(destination_file);
        callback_list_call_attr_0(this_->attr_cbl, attr_destination);
        if (this_->route) {
                route_set_destination(this_->route, c, async);
@@ -996,6 +1490,36 @@ navit_set_destination(struct navit *this_, struct pcoord *c, const char *descrip
 }
 
 /**
+ * Start the route computing to a given set of coordinates including waypoints
+ *
+ * @param navit The navit instance
+ * @param c The coordinate to start routing to
+ * @param description A label which allows the user to later identify this destination in the former destinations selection
+ * @returns nothing
+ */
+void
+navit_set_destinations(struct navit *this_, struct pcoord *c, int count, const char *description, int async)
+{
+       char *destination_file;
+       if (c && count) {
+               this_->destination=c[count-1];
+               this_->destination_valid=1;
+
+               destination_file = bookmarks_get_destination_file(TRUE);
+               bookmarks_append_coord(this_->former_destination, destination_file, c, type_former_itinerary, description, this_->recentdest_count);
+               g_free(destination_file);
+       } else
+               this_->destination_valid=0;
+       callback_list_call_attr_0(this_->attr_cbl, attr_destination);
+       if (this_->route) {
+               route_set_destinations(this_->route, c, count, async);
+
+               if (this_->ready == 3)
+                       navit_draw(this_);
+       }
+}
+
+/**
  * @brief Checks if a route is calculated
  *
  * This function checks if a route is calculated.
@@ -1013,42 +1537,10 @@ navit_check_route(struct navit *this_)
        return 0;
 }
 
-/**
- * Record the given set of coordinates as a bookmark
- *
- * @param navit The navit instance
- * @param c The coordinate to store
- * @param description A label which allows the user to later identify this bookmark
- * @returns nothing
- */
-void
-navit_add_bookmark(struct navit *this_, struct pcoord *c, const char *description)
-{
-       char *bookmark_file = navit_get_bookmark_file(TRUE);
-       navit_append_coord(this_,bookmark_file, c, "bookmark", description, this_->bookmarks_hash,0);
-       g_free(bookmark_file);
-
-       callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
-}
-
-struct navit *global_navit;
-
-static void
-navit_add_bookmarks_from_file(struct navit *this_)
-{
-       char *bookmark_file = navit_get_bookmark_file(FALSE);
-       struct attr parent={attr_navit, .u.navit=this_};
-       struct attr type={attr_type, {"textfile"}}, data={attr_data, {bookmark_file}};
-       struct attr *attrs[]={&type, &data, NULL};
-
-       this_->bookmark=map_new(&parent, attrs);
-       g_free(bookmark_file);
-}
-
 static int
 navit_former_destinations_active(struct navit *this_)
 {
-       char *destination_file = navit_get_destination_file(FALSE);
+       char *destination_file = bookmarks_get_destination_file(FALSE);
        FILE *f;
        int active=0;
        char buffer[3];
@@ -1062,35 +1554,56 @@ navit_former_destinations_active(struct navit *this_)
        return active;
 }
 
+struct map* read_former_destinations_from_file(){
+       struct attr type, data, flags, *attrs[4];
+       char *destination_file = bookmarks_get_destination_file(FALSE);
+       struct map *m;
+
+       type.type=attr_type;
+       type.u.str="textfile";
+
+       data.type=attr_data;
+       data.u.str=destination_file;
+
+       flags.type=attr_flags;
+       flags.u.num=1;
+
+       attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
+
+       m=map_new(NULL, attrs);
+       g_free(destination_file);
+       return m;
+}
+
 static void
 navit_add_former_destinations_from_file(struct navit *this_)
 {
-       char *destination_file = navit_get_destination_file(FALSE);
-       struct attr parent={attr_navit, .u.navit=this_};
-       struct attr type={attr_type, {"textfile"}}, data={attr_data, {destination_file}};
-       struct attr *attrs[]={&type, &data, NULL};
-       struct map_rect *mr;
        struct item *item;
-       int valid=0;
-       struct coord c;
-       struct pcoord pc;
+       int i,valid=0,count=0;
+       struct coord c[16];
+       struct pcoord pc[16];
+       struct map_rect *mr;
 
-       this_->former_destination=map_new(&parent, attrs);
-       g_free(destination_file);
+       this_->former_destination=read_former_destinations_from_file();
        if (!this_->route || !navit_former_destinations_active(this_))
                return; 
        mr=map_rect_new(this_->former_destination, NULL);
        while ((item=map_rect_get_item(mr))) {
-               if (item->type == type_former_destination && item_coord_get(item, &c, 1)) 
+               if ((item->type == type_former_destination || item->type == type_former_itinerary || item->type == type_former_itinerary_part) && (count=item_coord_get(item, c, 16))) 
                        valid=1;
        }
        map_rect_destroy(mr);
-       pc.pro=map_projection(this_->former_destination);
-       pc.x=c.x;
-       pc.y=c.y;
-       if (valid) {
-               route_set_destination(this_->route, &pc, 1);
-               this_->destination=pc;
+       if (valid && count > 0) {
+               for (i = 0 ; i < count ; i++) {
+                       pc[i].pro=map_projection(this_->former_destination);
+                       pc[i].x=c[i].x;
+                       pc[i].y=c[i].y;
+               }
+               if (count == 1)
+                       route_set_destination(this_->route, &pc[0], 1);
+               else
+                       route_set_destinations(this_->route, pc, count, 1);
+               this_->destination=pc[count-1];
                this_->destination_valid=1;
        }
 }
@@ -1112,16 +1625,33 @@ navit_textfile_debug_log(struct navit *this_, const char *fmt, ...)
                va_end(ap);
 }
 
-int 
-navit_speech_estimate(struct navit *this_, char *str)
+void
+navit_textfile_debug_log_at(struct navit *this_, struct pcoord *pc, const char *fmt, ...)
 {
-       return speech_estimate_duration(this_->speech, str);
+       va_list ap;
+       char *str1,*str2;
+       va_start(ap, fmt);
+       if (this_->textfile_debug_log && this_->vehicle) {
+               str1=g_strdup_vprintf(fmt, ap);
+               str2=g_strdup_printf("0x%x 0x%x%s%s\n", pc->x, pc->y, strlen(str1) ? " " : "", str1);
+               log_write(this_->textfile_debug_log, str2, strlen(str2), 0);
+               g_free(str2);
+               g_free(str1);
+       }
+               va_end(ap);
 }
 
 void
 navit_say(struct navit *this_, char *text)
 {
-       speech_say(this_->speech, text);
+       struct attr attr;
+       if(this_->speech) {
+               if (!speech_get_attr(this_->speech, attr_active, &attr, NULL))
+                       attr.u.num = 1;
+               dbg(1, "this_.speech->active %i\n", attr.u.num);
+               if(attr.u.num)
+                       speech_say(this_->speech, text);
+       }
 }
 
 /**
@@ -1280,6 +1810,7 @@ navit_window_roadbook_destroy(struct navit *this_)
 {
        dbg(0, "enter\n");
        navigation_unregister_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback);
+       callback_destroy(this_->roadbook_callback);
        this_->roadbook_window=NULL;
        this_->roadbook_callback=NULL;
 }
@@ -1302,20 +1833,22 @@ navit_init(struct navit *this_)
        struct mapset *ms;
        struct map *map;
        int callback;
+       char *center_file;
 
        dbg(2,"enter gui %p graphics %p\n",this_->gui,this_->gra);
-       if (!this_->gui) {
+
+       if (!this_->gui && !(this_->flags & 2)) {
                dbg(0,"no gui\n");
                navit_destroy(this_);
                return;
        }
-       if (!this_->gra) {
+       if (!this_->gra && !(this_->flags & 1)) {
                dbg(0,"no graphics\n");
                navit_destroy(this_);
                return;
        }
        dbg(2,"Connecting gui to graphics\n");
-       if (gui_set_graphics(this_->gui, this_->gra)) {
+       if (this_->gui && this_->gra && gui_set_graphics(this_->gui, this_->gra)) {
                struct attr attr_type_gui, attr_type_graphics;
                gui_get_attr(this_->gui, attr_type, &attr_type_gui, NULL);
                graphics_get_attr(this_->gra, attr_type, &attr_type_graphics, NULL);
@@ -1326,18 +1859,43 @@ navit_init(struct navit *this_)
                navit_destroy(this_);
                return;
        }
+       if (this_->speech && this_->navigation) {
+               struct attr speech;
+               speech.type=attr_speech;
+               speech.u.speech=this_->speech;
+               navigation_set_attr(this_->navigation, &speech);
+       }
        dbg(2,"Initializing graphics\n");
        dbg(2,"Setting Vehicle\n");
        navit_set_vehicle(this_, this_->vehicle);
        dbg(2,"Adding dynamic maps to mapset %p\n",this_->mapsets);
        if (this_->mapsets) {
+               struct mapset_handle *msh;
                ms=this_->mapsets->data;
+               this_->progress_cb=callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_);
+               msh=mapset_open(ms);
+               while (msh && (map=mapset_next(msh, 0))) {
+                       //pass new callback instance for each map in the mapset to make map callback list destruction work correctly
+                       struct callback *pcb = callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_);
+                       map_add_callback(map, pcb);
+               }
+               mapset_close(msh);
+               
                if (this_->route) {
-                       if ((map=route_get_map(this_->route)))
-                               mapset_add_attr(ms, &(struct attr){attr_map,.u.map=map});
+                       if ((map=route_get_map(this_->route))) {
+                               struct attr map_a;
+                               map_a.type=attr_map;
+                               map_a.u.map=map;
+                               mapset_add_attr(ms, &map_a);
+                       }
                        if ((map=route_get_graph_map(this_->route))) {
-                               mapset_add_attr(ms, &(struct attr){attr_map,.u.map=map});
-                               map_set_attr(map, &(struct attr ){attr_active,.u.num=0});
+                               struct attr map_a,active;
+                               map_a.type=attr_map;
+                               map_a.u.map=map;
+                               active.type=attr_active;
+                               active.u.num=0;
+                               mapset_add_attr(ms, &map_a);
+                               map_set_attr(map, &active);
                        }
                        route_set_mapset(this_->route, ms);
                        route_set_projection(this_->route, transform_get_projection(this_->trans));
@@ -1349,17 +1907,26 @@ navit_init(struct navit *this_)
                }
                if (this_->navigation) {
                        if ((map=navigation_get_map(this_->navigation))) {
-                               mapset_add_attr(ms, &(struct attr){attr_map,.u.map=map});
-                               map_set_attr(map, &(struct attr ){attr_active,.u.num=0});
+                               struct attr map_a,active;
+                               map_a.type=attr_map;
+                               map_a.u.map=map;
+                               active.type=attr_active;
+                               active.u.num=0;
+                               mapset_add_attr(ms, &map_a);
+                               map_set_attr(map, &active);
                        }
                }
                if (this_->tracking) {
                        if ((map=tracking_get_map(this_->tracking))) {
-                               mapset_add_attr(ms, &(struct attr){attr_map,.u.map=map});
-                               map_set_attr(map, &(struct attr ){attr_active,.u.num=0});
+                               struct attr map_a,active;
+                               map_a.type=attr_map;
+                               map_a.u.map=map;
+                               active.type=attr_active;
+                               active.u.num=0;
+                               mapset_add_attr(ms, &map_a);
+                               map_set_attr(map, &active);
                        }
                }
-               navit_add_bookmarks_from_file(this_);
                navit_add_former_destinations_from_file(this_);
        }
        if (this_->route) {
@@ -1378,8 +1945,8 @@ navit_init(struct navit *this_)
                        navigation_set_route(this_->navigation, this_->route);
        }
        dbg(2,"Setting Center\n");
-       char *center_file = navit_get_center_file(FALSE);
-       navit_set_center_from_file(this_, center_file);
+       center_file = bookmarks_get_center_file(FALSE);
+       bookmarks_set_center_from_file(this_->bookmarks, center_file);
        g_free(center_file);
 #if 0
        if (this_->menubar) {
@@ -1404,7 +1971,7 @@ navit_init(struct navit *this_)
        this_->ready|=1;
        dbg(2,"ready=%d\n",this_->ready);
        if (this_->ready == 3)
-               navit_draw(this_);
+               navit_draw_async(this_, 1);
        if (callback)
                callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_);
 #if 0
@@ -1413,6 +1980,34 @@ navit_init(struct navit *this_)
 }
 
 void
+navit_zoom_to_rect(struct navit *this_, struct coord_rect *r)
+{
+       struct coord c;
+       int scale=16;
+
+       c.x=(r->rl.x+r->lu.x)/2;
+       c.y=(r->rl.y+r->lu.y)/2;
+       transform_set_center(this_->trans, &c);
+       dbg(1,"%x,%x-%x,%x\n", r->rl.x,r->rl.y,r->lu.x,r->lu.y);
+       while (scale < 1<<20) {
+               struct point p1,p2;
+               transform_set_scale(this_->trans, scale);
+               transform_setup_source_rect(this_->trans);
+               transform(this_->trans, transform_get_projection(this_->trans), &r->lu, &p1, 1, 0, 0, NULL);
+               transform(this_->trans, transform_get_projection(this_->trans), &r->rl, &p2, 1, 0, 0, NULL);
+               dbg(1,"%d,%d-%d,%d\n",p1.x,p1.y,p2.x,p2.y);
+               if (p1.x < 0 || p2.x < 0 || p1.x > this_->w || p2.x > this_->w ||
+                   p1.y < 0 || p2.y < 0 || p1.y > this_->h || p2.y > this_->h)
+                       scale*=2;
+               else
+                       break;
+       
+       }
+       if (this_->ready == 3)
+               navit_draw_async(this_,0);
+}
+
+void
 navit_zoom_to_route(struct navit *this_, int orientation)
 {
        struct map *map;
@@ -1420,7 +2015,7 @@ navit_zoom_to_route(struct navit *this_, int orientation)
        struct item *item;
        struct coord c;
        struct coord_rect r;
-       int count=0,scale=16;
+       int count=0;
        if (! this_->route)
                return;
        dbg(1,"enter\n");
@@ -1441,32 +2036,13 @@ navit_zoom_to_route(struct navit *this_, int orientation)
                                count++;
                        }
                }
+               map_rect_destroy(mr);
        }
        if (! count)
                return;
-       c.x=(r.rl.x+r.lu.x)/2;
-       c.y=(r.rl.y+r.lu.y)/2;
-       dbg(1,"count=%d\n",count);
        if (orientation != -1)
                transform_set_yaw(this_->trans, orientation);
-       transform_set_center(this_->trans, &c);
-       dbg(1,"%x,%x-%x,%x\n", r.rl.x,r.rl.y,r.lu.x,r.lu.y);
-       while (scale < 1<<20) {
-               struct point p1,p2;
-               transform_set_scale(this_->trans, scale);
-               transform_setup_source_rect(this_->trans);
-               transform(this_->trans, transform_get_projection(this_->trans), &r.lu, &p1, 1, 0, 0, NULL);
-               transform(this_->trans, transform_get_projection(this_->trans), &r.rl, &p2, 1, 0, 0, NULL);
-               dbg(1,"%d,%d-%d,%d\n",p1.x,p1.y,p2.x,p2.y);
-               if (p1.x < 0 || p2.x < 0 || p1.x > this_->w || p2.x > this_->w ||
-                   p1.y < 0 || p2.y < 0 || p1.y > this_->h || p2.y > this_->h)
-                       scale*=2;
-               else
-                       break;
-       
-       }
-       if (this_->ready == 3)
-               navit_draw_async(this_,0);
+       navit_zoom_to_rect(this_, &r);
 }
 
 static void
@@ -1535,23 +2111,26 @@ navit_set_cursors(struct navit *this_)
        v=g_list_first(this_->vehicles); // GList of navit_vehicles
        while (v) {
                nv=v->data;
-               if (vehicle_get_attr(nv->vehicle, attr_cursorname, &name, NULL))
-                       c=layout_get_cursor(this_->layout_current, name.u.str);
-               else
+               if (vehicle_get_attr(nv->vehicle, attr_cursorname, &name, NULL)) {
+                       if (!strcmp(name.u.str,"none"))
+                               c=NULL;
+                       else
+                               c=layout_get_cursor(this_->layout_current, name.u.str);
+               } else
                        c=layout_get_cursor(this_->layout_current, "default");
-               vehicle_set_cursor(nv->vehicle, c);
+               vehicle_set_cursor(nv->vehicle, c, 0);
                v=g_list_next(v);
        }
        return;
 }
 
 static int
-navit_get_cursor_pnt(struct navit *this_, struct point *p, int *dir)
+navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir)
 {
        int width, height;
        struct navit_vehicle *nv=this_->vehicle;
 
-        float offset=30;            // Cursor offset from the center of the screen (percent).
+        float offset=this_->radius;      // Cursor offset from the center of the screen (percent).
 #if 0 /* Better improve track.c to get that issue resolved or make it configurable with being off the default, the jumping back to the center is a bit annoying */
         float min_offset = 0.;      // Percent offset at min_offset_speed.
         float max_offset = 30.;     // Percent offset at max_offset_speed.
@@ -1568,11 +2147,11 @@ navit_get_cursor_pnt(struct navit *this_, struct point *p, int *dir)
 #endif
 
        transform_get_size(this_->trans, &width, &height);
-       if (this_->orientation == -1) {
+       if (this_->orientation == -1 || keep_orientation) {
                p->x=50*width/100;
                p->y=(50 + offset)*height/100;
-               if (dir)
-                       *dir=nv->dir;
+               if (dir) 
+                       *dir=keep_orientation?this_->orientation:nv->dir;
        } else {
                int mdir;
                if (this_->tracking && this_->tracking_flag) {
@@ -1589,16 +2168,23 @@ navit_get_cursor_pnt(struct navit *this_, struct point *p, int *dir)
        return 1;
 }
 
-static void
-navit_set_center_cursor(struct navit *this_)
+void
+navit_set_center_cursor(struct navit *this_, int autozoom, int keep_orientation)
 {
        int dir;
        struct point pn;
        struct navit_vehicle *nv=this_->vehicle;
-       navit_get_cursor_pnt(this_, &pn, &dir);
+       navit_get_cursor_pnt(this_, &pn, keep_orientation, &dir);
        transform_set_yaw(this_->trans, dir);
        navit_set_center_coord_screen(this_, &nv->coord, &pn, 0);
-       navit_autozoom(this_, &nv->coord, nv->speed, 0);
+       if (autozoom)
+               navit_autozoom(this_, &nv->coord, nv->speed, 0);
+}
+
+static void
+navit_set_center_cursor_draw(struct navit *this_)
+{
+       navit_set_center_cursor(this_,1,0);
        if (this_->ready == 3)
                navit_draw_async(this_, 1);
 }
@@ -1606,7 +2192,7 @@ navit_set_center_cursor(struct navit *this_)
 static void
 navit_cmd_set_center_cursor(struct navit *this_)
 {
-       navit_set_center_cursor(this_);
+       navit_set_center_cursor_draw(this_);
 }
 
 void
@@ -1621,16 +2207,6 @@ navit_set_center_screen(struct navit *this_, struct point *p, int set_timeout)
        navit_set_center(this_, &pc, set_timeout);
 }
 
-#if 0
-               switch((*attrs)->type) {
-               case attr_zoom:
-                       zoom=(*attrs)->u.num;
-                       break;
-               case attr_center:
-                       g=*((*attrs)->u.coord_geo);
-                       break;
-#endif
-
 static int
 navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
 {
@@ -1639,8 +2215,10 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
        long zoom;
        GList *l;
        struct navit_vehicle *nv;
-       struct attr active=(struct attr){attr_active,{(void *)0}};
        struct layout *lay;
+       struct attr active;
+       active.type=attr_active;
+       active.u.num=0;
 
        switch (attr->type) {
        case attr_autozoom:
@@ -1660,6 +2238,10 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
                attr_updated=(this_->drag_bitmap != !!attr->u.num);
                this_->drag_bitmap=!!attr->u.num;
                break;
+       case attr_flags:
+               attr_updated=(this_->flags != attr->u.num);
+               this_->flags=attr->u.num;
+               break;
        case attr_flags_graphics:
                attr_updated=(this_->graphics_flags != attr->u.num);
                this_->graphics_flags=attr->u.num;
@@ -1693,6 +2275,12 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
                        l=g_list_next(l);
                }               
                return 0;
+       case attr_map_border:
+               if (this_->border != attr->u.num) {
+                       this_->border=attr->u.num;
+                       attr_updated=1;
+               }
+               break;
        case attr_orientation:
                orient_old=this_->orientation;
                this_->orientation=attr->u.num;
@@ -1728,10 +2316,14 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
                break;
        case attr_projection:
                if(this_->trans && transform_get_projection(this_->trans) != attr->u.projection) {
-                       navit_projection_set(this_, attr->u.projection);
+                       navit_projection_set(this_, attr->u.projection, !init);
                        attr_updated=1;
                }
                break;
+       case attr_radius:
+               attr_updated=(this_->radius != attr->u.num);
+               this_->radius=attr->u.num;
+               break;
        case attr_recent_dest:
                attr_updated=(this_->recentdest_count != attr->u.num);
                this_->recentdest_count=attr->u.num;
@@ -1750,6 +2342,9 @@ navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
                attr_updated=(this_->tracking_flag != !!attr->u.num);
                this_->tracking_flag=!!attr->u.num;
                break;
+       case attr_transformation:
+               this_->trans=attr->u.transformation;
+               break;
        case attr_use_mousewheel:
                attr_updated=(this_->use_mousewheel != !!attr->u.num);
                this_->use_mousewheel=!!attr->u.num;
@@ -1793,6 +2388,10 @@ 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; 
        default:
                return 0;
        }
@@ -1845,8 +2444,14 @@ navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, stru
 
                attr->u.str[len] = '\0';
                break;
+        case attr_imperial: 
+                attr->u.num=this_->imperial; 
+                break; 
        case attr_bookmark_map:
-               attr->u.map=this_->bookmark;
+               attr->u.map=bookmarks_get_map(this_->bookmarks);
+               break;
+       case attr_bookmarks:
+               attr->u.bookmarks=this_->bookmarks;
                break;
        case attr_callback_list:
                attr->u.callback_list=this_->attr_cbl;
@@ -1905,13 +2510,17 @@ navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, stru
                break;
        case attr_mapset:
                attr->u.mapset=this_->mapsets->data;
-               return (attr->u.mapset != NULL);
+               ret=(attr->u.mapset != NULL);
+               break;
        case attr_navigation:
                attr->u.navigation=this_->navigation;
                break;
        case attr_orientation:
                attr->u.num=this_->orientation;
                break;
+       case attr_osd:
+               ret=attr_generic_get_attr(this_->attr_list, NULL, type, attr, iter?(struct attr_iter *)&iter->iter:NULL);
+               break;
        case attr_osd_configuration:
                attr->u.num=this_->osd_configuration;
                break;
@@ -1934,6 +2543,9 @@ navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, stru
        case attr_tracking:
                attr->u.num=this_->tracking_flag;
                break;
+       case attr_trackingo:
+               attr->u.tracking=this_->tracking;
+               break;
        case attr_transformation:
                attr->u.transformation=this_->trans;
                break;
@@ -1955,6 +2567,9 @@ navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, stru
                        }
                }
                break;
+       case attr_vehicleprofile:
+               attr->u.vehicleprofile=this_->vehicleprofile;
+               break;
        case attr_zoom:
                attr->u.num=transform_get_scale(this_->trans);
                break;
@@ -1988,6 +2603,19 @@ navit_add_log(struct navit *this_, struct log *log)
        return 0;
 }
 
+static int
+navit_add_layout(struct navit *this_, struct layout *layout)
+{
+       struct attr active;
+       this_->layouts = g_list_append(this_->layouts, layout);
+       layout_get_attr(layout, attr_active, &active, NULL);
+       if(active.u.num || !this_->layout_current) { 
+               this_->layout_current=layout;
+               return 1;
+       }
+       return 0;
+}
+
 int
 navit_add_attr(struct navit *this_, struct attr *attr)
 {
@@ -2006,9 +2634,7 @@ navit_add_attr(struct navit *this_, struct attr *attr)
                ret=navit_set_graphics(this_, attr->u.graphics);
                break;
        case attr_layout:
-               this_->layouts = g_list_append(this_->layouts, attr->u.layout);
-               if(!this_->layout_current) 
-                       this_->layout_current=attr->u.layout;
+               ret=navit_add_layout(this_, attr->u.layout);
                break;
        case attr_route:
                this_->route=attr->u.route;
@@ -2019,6 +2645,9 @@ navit_add_attr(struct navit *this_, struct attr *attr)
        case attr_navigation:
                this_->navigation=attr->u.navigation;
                break;
+       case attr_osd:
+               this_->attr_list=attr_generic_add_attr(this_->attr_list, attr);
+               break;
        case attr_recent_dest:
                this_->recentdest_count = attr->u.num;
                break;
@@ -2100,10 +2729,12 @@ navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *
        if (pnt)
                cursor_pnt=*pnt;
        else {
-               pro=transform_get_projection(this_->trans);
-               transform(this_->trans, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
+               pro=transform_get_projection(this_->trans_cursor);
+               if (!pro)
+                       return;
+               transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
        }
-       vehicle_draw(nv->vehicle, this_->gra, &cursor_pnt, pnt ? 0:1, nv->dir-transform_get_yaw(this_->trans), nv->speed);
+       vehicle_draw(nv->vehicle, this_->gra, &cursor_pnt, pnt ? 0:1, nv->dir-transform_get_yaw(this_->trans_cursor), nv->speed);
 #if 0  
        if (pnt)
                pnt2=*pnt;
@@ -2126,10 +2757,12 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
        struct pcoord cursor_pc;
        struct point cursor_pnt, *pnt=&cursor_pnt;
        struct tracking *tracking=NULL;
-       enum projection pro=transform_get_projection(this_->trans);
-       int border=16;
+       struct pcoord pc[16];
+       enum projection pro=transform_get_projection(this_->trans_cursor);
+       int count;
        int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *);
        void *attr_object;
+       char *destination_file;
 
        profile(0,NULL);
        if (this_->ready != 3) {
@@ -2176,12 +2809,12 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
        callback_list_call_attr_0(this_->attr_cbl, attr_position);
        navit_textfile_debug_log(this_, "type=trackpoint_tracked");
        if (this_->gui && nv->speed > 2)
-               gui_disable_suspend(this_->gui);
+               navit_disable_suspend();
 
-       transform(this_->trans, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
+       transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
        if (this_->button_pressed != 1 && this_->follow_cursor && nv->follow_curr <= nv->follow && 
-               (nv->follow_curr == 1 || !transform_within_border(this_->trans, &cursor_pnt, border)))
-               navit_set_center_cursor(this_);
+               (nv->follow_curr == 1 || !transform_within_border(this_->trans_cursor, &cursor_pnt, this_->border)))
+               navit_set_center_cursor_draw(this_);
        else
                navit_vehicle_draw(this_, nv, pnt);
 
@@ -2192,8 +2825,18 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
        callback_list_call_attr_2(this_->attr_cbl, attr_position_coord_geo, this_, nv->vehicle);
 
        /* Finally, if we reached our destination, stop navigation. */
-       if (this_->route && route_destination_reached(this_->route)) {
-               navit_set_destination(this_, NULL, NULL, 0);
+       if (this_->route) {
+               switch(route_destination_reached(this_->route)) {
+               case 1:
+                       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);
+                       break;  
+               case 2:
+                       navit_set_destination(this_, NULL, NULL, 0);
+                       break;
+               }
        }
        profile(0,"return 5\n");
 }
@@ -2246,7 +2889,17 @@ navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv)
                if (navit_set_vehicleprofile(this_, attr.u.str))
                        return;
        }
-       navit_set_vehicleprofile(this_,"car");
+       if (!navit_set_vehicleprofile(this_,"car")) {
+               /* We do not have a fallback "car" profile
+               * so lets set any profile */
+               GList *l;
+               l=this_->vehicleprofiles;
+               if (l) {
+                   this_->vehicleprofile=l->data;
+                   if (this_->route)
+                       route_set_profile(this_->route, this_->vehicleprofile);
+               }
+       }
 }
 
 /**
@@ -2267,7 +2920,7 @@ navit_add_vehicle(struct navit *this_, struct vehicle *v)
        nv->last.y = 0;
        nv->animate_cursor=0;
        if ((vehicle_get_attr(v, attr_follow, &follow, NULL)))
-               nv->follow=nv->follow=follow.u.num;
+               nv->follow=follow.u.num;
        nv->follow_curr=nv->follow;
        this_->vehicles=g_list_append(this_->vehicles, nv);
        if ((vehicle_get_attr(v, attr_active, &active, NULL)) && active.u.num)
@@ -2327,6 +2980,8 @@ navit_layout_switch(struct navit *n)
     if (navit_get_attr(n,attr_layout,&layout_attr,NULL)!=1) {
        return; //No layout - nothing to switch
     }
+    if (!n->vehicle)
+       return;
     l=layout_attr.u.layout;
     
     if (l->dayname || l->nightname) {
@@ -2335,6 +2990,7 @@ navit_layout_switch(struct navit *n)
        //Check that we aren't calculating too fast
        if (vehicle_get_attr(n->vehicle->vehicle, attr_position_time_iso8601,&iso8601_attr,NULL)==1) {
                currTs=iso8601_to_secs(iso8601_attr.u.str);
+               dbg(1,"currTs: %u:%u\n",currTs%86400/3600,((currTs%86400)%3600)/60);
        }
        if (currTs-(n->prevTs)<60) {
            //We've have to wait a little
@@ -2342,23 +2998,24 @@ navit_layout_switch(struct navit *n)
        }
        if (sscanf(iso8601_attr.u.str,"%d-%02d-%02dT",&year,&month,&day) != 3)
                return;
+       if (vehicle_get_attr(n->vehicle->vehicle, attr_position_valid, &valid_attr,NULL) && valid_attr.u.num==attr_position_valid_invalid) {
+               return; //No valid fix yet
+       }
        if (vehicle_get_attr(n->vehicle->vehicle, attr_position_coord_geo,&geo_attr,NULL)!=1) {
                //No position - no sun
                return;
        }
-       if (vehicle_get_attr(n->vehicle->vehicle, attr_position_valid, &valid_attr,NULL) && valid_attr.u.num==attr_position_valid_invalid) {
-               return; //No valid fix yet
-       }
        
-       //We calculate sunrise anyway, cause it is need both for day and for night
-        if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lat,geo_attr.u.coord_geo->lng,35,1,&trise,&tset)!=0) {
+       //We calculate sunrise anyway, cause it is needed both for day and for night
+        if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,-5,1,&trise,&tset)!=0) {
                //near the pole sun never rises/sets, so we should never switch profiles
+               dbg(1,"trise: %u:%u, sun never visible, never switch profile\n",HOURS(trise),MINUTES(trise));
                n->prevTs=currTs;
                return;
            }
        
         trise_actual=trise;
-       
+       dbg(1,"trise: %u:%u\n",HOURS(trise),MINUTES(trise));
        if (l->dayname) {
        
            if ((HOURS(trise)*60+MINUTES(trise)==(currTs%86400)/60) || 
@@ -2370,12 +3027,13 @@ navit_layout_switch(struct navit *n)
            }
        }
        if (l->nightname) {
-           if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lat,geo_attr.u.coord_geo->lng,-12,0,&trise,&tset)!=0) {
+           if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,-5,1,&trise,&tset)!=0) {
                //near the pole sun never rises/sets, so we should never switch profiles
+               dbg(1,"tset: %u:%u, sun always visible, never switch profile\n",HOURS(tset),MINUTES(tset));
                n->prevTs=currTs;
                return;
            }
-           
+           dbg(1,"tset: %u:%u\n",HOURS(tset),MINUTES(tset));
            if (HOURS(tset)*60+MINUTES(tset)==((currTs%86400)/60)
                || (n->prevTs==0 && (((HOURS(tset)*60+MINUTES(tset)<(currTs%86400)/60)) || 
                        ((HOURS(trise_actual)*60+MINUTES(trise_actual)>(currTs%86400)/60))))) {
@@ -2391,7 +3049,31 @@ navit_layout_switch(struct navit *n)
 }
 
 int 
-navit_set_layout_by_name(struct navit *n,char *name) 
+navit_set_vehicle_by_name(struct navit *n,const char *name) 
+{
+    struct vehicle *v;
+    struct attr_iter *iter;
+    struct attr vehicle_attr, name_attr;
+
+       iter=navit_attr_iter_new();
+
+    while (navit_get_attr(n,attr_vehicle,&vehicle_attr,iter)) {
+               v=vehicle_attr.u.vehicle;
+               vehicle_get_attr(v,attr_name,&name_attr,NULL);
+               if (name_attr.type==attr_name) {
+                       if (!strcmp(name,name_attr.u.str)) {
+                               navit_set_attr(n,&vehicle_attr);                                
+                               navit_attr_iter_destroy(iter);
+                               return 1;
+                       }
+               }
+       }
+    navit_attr_iter_destroy(iter);
+    return 0;
+}
+
+int 
+navit_set_layout_by_name(struct navit *n,const char *name) 
 {
     struct layout *l;
     struct attr_iter iter;
@@ -2424,16 +3106,22 @@ navit_set_layout_by_name(struct navit *n,char *name)
     return 0;
 }
 
+void
+navit_disable_suspend() {
+       gui_disable_suspend(global_navit->gui);
+       callback_list_call_attr_0(global_navit->attr_cbl,attr_unsuspend);
+}
+
 int
 navit_block(struct navit *this_, int block)
 {
-       if (block) {
+       if (block > 0) {
                this_->blocked |= 1;
                if (graphics_draw_cancel(this_->gra, this_->displaylist))
                        this_->blocked |= 2;
                return 0;
        }
-       if (this_->blocked & 2) {
+       if ((this_->blocked & 2) || block < 0) {
                this_->blocked=0;
                navit_draw(this_);
                return 1;
@@ -2445,16 +3133,23 @@ navit_block(struct navit *this_, int block)
 void
 navit_destroy(struct navit *this_)
 {
+       struct mapset*ms;
+       callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_);
+
        /* TODO: destroy objects contained in this_ */
        if (this_->vehicle)
                vehicle_destroy(this_->vehicle->vehicle);
-       char *center_file = navit_get_center_file(TRUE);
-       navit_write_center_to_file(this_, center_file);
-       g_free(center_file);
+       if (this_->bookmarks) {
+               char *center_file = bookmarks_get_center_file(TRUE);
+               bookmarks_write_center_to_file(this_->bookmarks, center_file);
+               g_free(center_file);
+               bookmarks_destroy(this_->bookmarks);
+       }
        callback_destroy(this_->nav_speech_cb);
        callback_destroy(this_->roadbook_callback);
        callback_destroy(this_->popup_callback);
        callback_destroy(this_->motion_timeout_callback);
+       callback_destroy(this_->progress_cb);
        if(this_->gra)
          graphics_remove_callback(this_->gra, this_->resize_callback);
        callback_destroy(this_->resize_callback);
@@ -2464,6 +3159,14 @@ navit_destroy(struct navit *this_)
        if(this_->gra)
          graphics_remove_callback(this_->gra, this_->motion_callback);
        callback_destroy(this_->motion_callback);
+       if(this_->gra)
+         graphics_remove_callback(this_->gra, this_->predraw_callback);
+       callback_destroy(this_->predraw_callback);
+       route_destroy(this_->route);
+       ms = navit_get_mapset(this_);
+       if(ms)
+               mapset_destroy(ms);
+       graphics_free(this_->gra);
        g_free(this_);
 }