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

Contents of /navit/navit/navit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (hide annotations) (download)
Mon Nov 21 20:53:45 2011 UTC (12 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 91954 byte(s)
better search, destination reached
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2009 Navit Team
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     #define _USE_MATH_DEFINES 1
21     #include "config.h"
22     #ifdef HAVE_UNISTD_H
23     #include <unistd.h>
24     #endif
25     #include <stdio.h>
26     #include <stdlib.h>
27     #include <signal.h>
28     #include <string.h>
29     #include <fcntl.h>
30     #include <glib.h>
31     #include <math.h>
32     #include <time.h>
33     #include "debug.h"
34     #include "navit.h"
35     #include "callback.h"
36     #include "gui.h"
37     #include "item.h"
38     #include "projection.h"
39     #include "map.h"
40     #include "mapset.h"
41     #include "main.h"
42     #include "coord.h"
43     #include "point.h"
44     #include "transform.h"
45     #include "param.h"
46     #include "menu.h"
47     #include "graphics.h"
48     #include "popup.h"
49     #include "data_window.h"
50     #include "route.h"
51     #include "navigation.h"
52     #include "speech.h"
53     #include "track.h"
54     #include "vehicle.h"
55     #include "layout.h"
56     #include "log.h"
57     #include "attr.h"
58     #include "event.h"
59     #include "file.h"
60     #include "profile.h"
61     #include "command.h"
62     #include "navit_nls.h"
63     #include "map.h"
64     #include "util.h"
65     #include "messages.h"
66     #include "vehicleprofile.h"
67     #include "sunriset.h"
68     #include "bookmarks.h"
69     #ifdef HAVE_API_WIN32_BASE
70     #include <windows.h>
71     #include "util.h"
72     #endif
73     #ifdef HAVE_API_WIN32_CE
74     #include "libc.h"
75     #endif
76    
77     /**
78     * @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
79     * @{
80     */
81    
82    
83     struct gui *main_loop_gui;
84    
85     struct attr_iter {
86     union {
87     GList *list;
88     struct mapset_handle *mapset_handle;
89     } u;
90     };
91    
92     static void navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv);
93     static void navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt);
94     static int navit_add_vehicle(struct navit *this_, struct vehicle *v);
95     static int navit_set_attr_do(struct navit *this_, struct attr *attr, int init);
96     static int navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir);
97     static void navit_set_cursors(struct navit *this_);
98     static void navit_cmd_zoom_to_route(struct navit *this);
99     static void navit_cmd_set_center_cursor(struct navit *this_);
100     static void navit_cmd_announcer_toggle(struct navit *this_);
101     static void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv);
102    
103     int allow_gui_internal = 0;
104     int routing_mode = 0;
105     int MYSTERY_SPEED = 2;
106 zoff99 14 int offline_search_filter_duplicates = 0;
107     int offline_search_break_searching = 0;
108 zoff99 2
109     struct navit *global_navit;
110    
111     void
112     navit_add_mapset(struct navit *this_, struct mapset *ms)
113     {
114     //dbg(0,"EEnter\n");
115     this_->mapsets = g_list_append(this_->mapsets, ms);
116     }
117    
118     struct mapset *
119     navit_get_mapset(struct navit *this_)
120     {
121     //dbg(0,"EEnter\n");
122     if(this_->mapsets){
123     return this_->mapsets->data;
124     } else {
125     dbg(0,"No mapsets enabled! Is it on purpose? Navit can't draw a map. Please check your navit.xml\n");
126     }
127     return NULL;
128     }
129    
130     struct tracking *
131     navit_get_tracking(struct navit *this_)
132     {
133     //dbg(0,"EEnter\n");
134     return this_->tracking;
135     }
136    
137     /**
138     * @brief Get the user data directory.
139     * @param[in] create - create the directory if it does not exist
140     *
141     * @return char * to the data directory string.
142     *
143     * returns the directory used to store user data files (center.txt,
144     * destination.txt, bookmark.txt, ...)
145     *
146     */
147     char*
148     navit_get_user_data_directory(int create) {
149     //dbg(0,"EEnter\n");
150     char *dir;
151     dir = getenv("NAVIT_USER_DATADIR");
152     if (create && !file_exists(dir)) {
153     dbg(0,"creating dir %s\n", dir);
154     if (file_mkdir(dir,0)) {
155     dbg(0,"failed creating dir %s\n", dir);
156     return NULL;
157     }
158     }
159     return dir;
160     } /* end: navit_get_user_data_directory(gboolean create) */
161    
162    
163     void
164     navit_draw_async(struct navit *this_, int async)
165     {
166     //dbg(0,"EEnter this_->blocked=%d\n",this_->blocked);
167     if (this_->blocked)
168     {
169     this_->blocked |= 2;
170     //dbg(0,"set this_->blocked=%d\n",this_->blocked);
171     return;
172     }
173     transform_setup_source_rect(this_->trans);
174     graphics_draw(this_->gra, this_->displaylist, this_->mapsets->data, this_->trans, this_->layout_current, async, NULL, this_->graphics_flags|1);
175     }
176    
177     void
178     navit_draw(struct navit *this_)
179     {
180     //dbg(0,"EEnter this_->ready=%d\n",this_->ready);
181     if (this_->ready == 3)
182     {
183     //dbg(0,"navit_draw_async_001\n");
184     navit_draw_async(this_, 0);
185     }
186     }
187    
188     int
189     navit_get_ready(struct navit *this_)
190     {
191     //dbg(0,"EEnter\n");
192     return this_->ready;
193     }
194    
195    
196    
197     void
198     navit_draw_displaylist(struct navit *this_)
199     {
200     //dbg(0,"EEnter\n");
201     if (this_->ready == 3)
202     {
203     // dbg(0,"call graphics_displaylist_draw 2")
204     graphics_displaylist_draw(this_->gra, this_->displaylist, this_->trans, this_->layout_current, this_->graphics_flags|1);
205     }
206     }
207    
208     static void
209     navit_map_progress(struct navit *this_)
210     {
211     //dbg(0,"EEnter\n");
212     struct map *map;
213     struct mapset *ms;
214     struct mapset_handle *msh;
215     struct attr attr;
216     struct point p;
217     if (this_->ready != 3)
218     return;
219     p.x=10;
220     p.y=32;
221    
222     ms=this_->mapsets->data;
223     msh=mapset_open(ms);
224     while (msh && (map=mapset_next(msh, 0))) {
225     if (map_get_attr(map, attr_progress, &attr, NULL)) {
226     char *str=g_strdup_printf("%s ",attr.u.str);
227     graphics_draw_mode(this_->gra, draw_mode_begin);
228     graphics_draw_text_std(this_->gra, 16, str, &p);
229     g_free(str);
230     p.y+=32;
231     graphics_draw_mode(this_->gra, draw_mode_end);
232     }
233     }
234     mapset_close(msh);
235     }
236    
237     static void
238     navit_redraw_route(struct navit *this_, struct route *route, struct attr *attr)
239     {
240     //dbg(0,"EEnter\n");
241     int updated;
242    
243     if ((this_->route)&&(this_->route->route_status_was_updated == 1))
244     {
245     this_->route->route_status_was_updated=0;
246     // send route_status to java
247     #ifdef HAVE_API_ANDROID
248     android_return_generic_int(1, this_->route->route_status);
249     #endif
250     }
251    
252     if (attr->type != attr_route_status)
253     {
254     //dbg(0,"ret 1\n");
255     return;
256     }
257     updated=attr->u.num;
258     //dbg(0,"updated=%d\n", updated);
259     if (this_->ready != 3)
260     {
261     //dbg(0,"ret 2\n");
262     return;
263     }
264     if (updated != route_status_path_done_new)
265     {
266     //dbg(0,"ret 3\n");
267     return;
268     }
269     if (this_->vehicle)
270     {
271     if (this_->vehicle->follow_curr == 1)
272     {
273     //dbg(0,"ret 4\n");
274     //dbg(0,"disabled -> we want redraw!!\n");
275     // return;
276     }
277     if (this_->vehicle->follow_curr <= this_->vehicle->follow)
278     {
279     this_->vehicle->follow_curr=this_->vehicle->follow;
280     }
281     }
282     //dbg(0,"draw s*\n");
283     navit_draw(this_);
284     //dbg(0,"draw e*\n");
285     }
286    
287     void
288     navit_handle_resize(struct navit *this_, int w, int h)
289     {
290     //dbg(0,"EEnter\n");
291     struct map_selection sel;
292     int callback=(this_->ready == 1);
293     //dbg(0,"pre this_->ready=%d\n",this_->ready);
294     this_->ready |= 2;
295     //dbg(0,"set this_->ready=%d\n",this_->ready);
296     memset(&sel, 0, sizeof(sel));
297     this_->w=w;
298     this_->h=h;
299     sel.u.p_rect.rl.x=w;
300     sel.u.p_rect.rl.y=h;
301     transform_set_screen_selection(this_->trans, &sel);
302     graphics_init(this_->gra);
303     graphics_set_rect(this_->gra, &sel.u.p_rect);
304     if (callback)
305     callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_);
306     if (this_->ready == 3)
307     {
308     //dbg(0,"navit_draw_async_002\n");
309     navit_draw_async(this_, 1);
310     }
311     }
312    
313     static void
314     navit_resize(void *data, int w, int h)
315     {
316     //dbg(0,"EEnter\n");
317     struct navit *this=data;
318     if (!this->ignore_graphics_events)
319     navit_handle_resize(this, w, h);
320     }
321    
322     int
323     navit_get_width(struct navit *this_)
324     {
325     //dbg(0,"EEnter\n");
326     return this_->w;
327     }
328    
329    
330     int
331     navit_get_height(struct navit *this_)
332     {
333     //dbg(0,"EEnter\n");
334     return this_->h;
335     }
336    
337     static void
338     navit_popup(void *data)
339     {
340     //dbg(0,"EEnter\n");
341     struct navit *this_=data;
342     popup(this_, 1, &this_->pressed);
343     this_->button_timeout=NULL;
344     this_->popped=1;
345     }
346    
347    
348     int
349     navit_ignore_button(struct navit *this_)
350     {
351     //dbg(0,"EEnter\n");
352     if (this_->ignore_button)
353     return 1;
354     this_->ignore_button=1;
355     return 0;
356     }
357    
358     void
359     navit_ignore_graphics_events(struct navit *this_, int ignore)
360     {
361     //dbg(0,"EEnter\n");
362     this_->ignore_graphics_events=ignore;
363     }
364    
365     static void
366     update_transformation(struct transformation *tr, struct point *old, struct point *new, struct point *rot)
367     {
368     //dbg(0,"EEnter\n");
369     struct coord co,cn;
370     struct coord c,*cp;
371     int yaw;
372     double angleo,anglen;
373    
374     if (!transform_reverse(tr, old, &co))
375     return;
376     if (rot) {
377     angleo=atan2(old->y-rot->y, old->x-rot->x)*180/M_PI;
378     anglen=atan2(new->y-rot->y, new->x-rot->x)*180/M_PI;
379     yaw=transform_get_yaw(tr)+angleo-anglen;
380     transform_set_yaw(tr, yaw % 360);
381     }
382     if (!transform_reverse(tr, new, &cn))
383     return;
384     cp=transform_get_center(tr);
385     c.x=cp->x+co.x-cn.x;
386     c.y=cp->y+co.y-cn.y;
387     dbg(1,"from 0x%x,0x%x to 0x%x,0x%x\n", cp->x, cp->y, c.x, c.y);
388     transform_set_center(tr, &c);
389     }
390    
391     void
392     navit_set_timeout(struct navit *this_)
393     {
394     //dbg(0,"EEnter\n");
395     struct attr follow;
396     follow.type=attr_follow;
397     follow.u.num=this_->center_timeout;
398     navit_set_attr(this_, &follow);
399     }
400    
401     int
402     navit_handle_button(struct navit *this_, int pressed, int button, struct point *p, struct callback *popup_callback)
403     {
404     //dbg(0,"EEnter\n");
405     int border=16;
406    
407     dbg(1,"enter %d %d (ignore %d)\n",pressed,button,this_->ignore_button);
408     callback_list_call_attr_4(this_->attr_cbl, attr_button, this_, GINT_TO_POINTER(pressed), GINT_TO_POINTER(button), p);
409     if (this_->ignore_button) {
410     this_->ignore_button=0;
411     return 0;
412     }
413     if (pressed) {
414     this_->pressed=*p;
415     this_->last=*p;
416     this_->zoomed=0;
417     if (button == 1) {
418     this_->button_pressed=1;
419     this_->moved=0;
420     this_->popped=0;
421     if (popup_callback)
422     this_->button_timeout=event_add_timeout(500, 0, popup_callback);
423     }
424     if (button == 2)
425     navit_set_center_screen(this_, p, 1);
426     if (button == 3)
427     popup(this_, button, p);
428     if (button == 4 && this_->use_mousewheel) {
429     this_->zoomed = 1;
430     navit_zoom_in(this_, 2, p);
431     }
432     if (button == 5 && this_->use_mousewheel) {
433     this_->zoomed = 1;
434     navit_zoom_out(this_, 2, p);
435     }
436     } else {
437    
438     this_->button_pressed=0;
439     if (this_->button_timeout) {
440     event_remove_timeout(this_->button_timeout);
441     this_->button_timeout=NULL;
442     if (! this_->moved && ! transform_within_border(this_->trans, p, border)) {
443     navit_set_center_screen(this_, p, !this_->zoomed);
444     }
445     }
446     if (this_->motion_timeout) {
447     event_remove_timeout(this_->motion_timeout);
448     this_->motion_timeout=NULL;
449     }
450     if (this_->moved) {
451     struct point pr;
452     pr.x=this_->w/2;
453     pr.y=this_->h;
454     #if 0
455     update_transformation(this_->trans, &this_->pressed, p, &pr);
456     #else
457     update_transformation(this_->trans, &this_->pressed, p, NULL);
458     #endif
459     graphics_draw_drag(this_->gra, NULL);
460     transform_copy(this_->trans, this_->trans_cursor);
461     graphics_overlay_disable(this_->gra, 0);
462     if (!this_->zoomed)
463     navit_set_timeout(this_);
464     navit_draw(this_);
465     } else
466     return 1;
467     }
468     return 0;
469     }
470    
471     static void
472     navit_button(void *data, int pressed, int button, struct point *p)
473     {
474     //dbg(0,"EEnter\n");
475     struct navit *this=data;
476     dbg(1,"enter %d %d ignore %d\n",pressed,button,this->ignore_graphics_events);
477     if (!this->ignore_graphics_events) {
478     if (! this->popup_callback)
479     this->popup_callback=callback_new_1(callback_cast(navit_popup), this);
480     navit_handle_button(this, pressed, button, p, this->popup_callback);
481     }
482     }
483    
484    
485     static void
486     navit_motion_timeout(struct navit *this_)
487     {
488     //dbg(0,"EEnter\n");
489     int dx, dy;
490    
491     if (this_->drag_bitmap) {
492     struct point point;
493     point.x=(this_->current.x-this_->pressed.x);
494     point.y=(this_->current.y-this_->pressed.y);
495     if (graphics_draw_drag(this_->gra, &point)) {
496     graphics_overlay_disable(this_->gra, 1);
497     graphics_draw_mode(this_->gra, draw_mode_end);
498     this_->moved=1;
499     this_->motion_timeout=NULL;
500     return;
501     }
502     }
503     dx=(this_->current.x-this_->last.x);
504     dy=(this_->current.y-this_->last.y);
505     if (dx || dy) {
506     struct transformation *tr;
507     struct point pr;
508     this_->last=this_->current;
509     graphics_overlay_disable(this_->gra, 1);
510     tr=transform_dup(this_->trans);
511     pr.x=this_->w/2;
512     pr.y=this_->h;
513     #if 0
514     update_transformation(tr, &this_->pressed, &this_->current, &pr);
515     #else
516     update_transformation(tr, &this_->pressed, &this_->current, NULL);
517     #endif
518     #if 0
519     graphics_displaylist_move(this_->displaylist, dx, dy);
520     #endif
521     graphics_draw_cancel(this_->gra, this_->displaylist);
522     // dbg(0,"call graphics_displaylist_draw 1")
523     graphics_displaylist_draw(this_->gra, this_->displaylist, tr, this_->layout_current, this_->graphics_flags);
524     transform_destroy(tr);
525     this_->moved=1;
526     }
527     this_->motion_timeout=NULL;
528     return;
529     }
530    
531     void
532     navit_handle_motion(struct navit *this_, struct point *p)
533     {
534     //dbg(0,"EEnter\n");
535     int dx, dy;
536    
537     if (this_->button_pressed && !this_->popped) {
538     dx=(p->x-this_->pressed.x);
539     dy=(p->y-this_->pressed.y);
540     if (dx < -8 || dx > 8 || dy < -8 || dy > 8) {
541     this_->moved=1;
542     if (this_->button_timeout) {
543     event_remove_timeout(this_->button_timeout);
544     this_->button_timeout=NULL;
545     }
546     this_->current=*p;
547     if (! this_->motion_timeout_callback)
548     this_->motion_timeout_callback=callback_new_1(callback_cast(navit_motion_timeout), this_);
549     if (! this_->motion_timeout)
550     this_->motion_timeout=event_add_timeout(100, 0, this_->motion_timeout_callback);
551     }
552     }
553     }
554    
555     static void
556     navit_motion(void *data, struct point *p)
557     {
558     //dbg(0,"EEnter\n");
559     struct navit *this=data;
560     if (!this->ignore_graphics_events)
561     navit_handle_motion(this, p);
562     }
563    
564     static void
565     navit_predraw(struct navit *this_)
566     {
567     //dbg(0,"EEnter\n");
568     GList *l;
569     struct navit_vehicle *nv;
570     transform_copy(this_->trans, this_->trans_cursor);
571     l=this_->vehicles;
572     while (l)
573     {
574     nv=l->data;
575     //dbg(0,"* here *\n");
576     //dbg(0,"vehicle_draw_004\n");
577     navit_vehicle_draw(this_, nv, NULL);
578     l=g_list_next(l);
579     }
580     }
581    
582     static void
583     navit_scale(struct navit *this_, long scale, struct point *p, int draw)
584     {
585     //dbg(0,"EEnter\n");
586     struct coord c1, c2, *center;
587    
588     if (scale < this_->zoom_min)
589     {
590     scale=this_->zoom_min;
591     }
592    
593     if (scale > this_->zoom_max)
594     {
595     scale=this_->zoom_max;
596     }
597    
598     // return scale value to android
599     #ifdef HAVE_API_ANDROID
600     android_return_generic_int(3, (int)scale);
601     #endif
602    
603     if (p)
604     {
605     transform_reverse(this_->trans, p, &c1);
606     }
607    
608     transform_set_scale(this_->trans, scale);
609    
610     if (p)
611     {
612     transform_reverse(this_->trans, p, &c2);
613     center = transform_center(this_->trans);
614     center->x += c1.x - c2.x;
615     center->y += c1.y - c2.y;
616     }
617    
618     if (draw)
619     {
620     navit_draw(this_);
621     }
622     }
623    
624     /**
625     * @brief Automatically adjusts zoom level
626     *
627     * This function automatically adjusts the current
628     * zoom level according to the current speed.
629     *
630     * @param this_ The navit struct
631     * @param center The "immovable" point - i.e. the vehicles position if we're centering on the vehicle
632     * @param speed The vehicles speed in meters per second
633     * @param dir The direction into which the vehicle moves
634     */
635     static void
636     navit_autozoom(struct navit *this_, struct coord *center, int speed, int draw)
637     {
638     struct point pc;
639     int distance,w,h;
640     double new_scale;
641     long scale;
642    
643     if (! this_->autozoom_active) {
644     return;
645     }
646    
647     distance = speed * this_->autozoom_secs;
648    
649     transform_get_size(this_->trans, &w, &h);
650     transform(this_->trans, transform_get_projection(this_->trans), center, &pc, 1, 0, 0, NULL);
651     scale = transform_get_scale(this_->trans);
652    
653     /* We make sure that the point we want to see is within a certain range
654     * around the vehicle. The radius of this circle is the size of the
655     * screen. This doesn't necessarily mean the point is visible because of
656     * perspective etc. Quite rough, but should be enough. */
657    
658     if (w > h) {
659     new_scale = (double)distance / h * 16;
660     } else {
661     new_scale = (double)distance / w * 16;
662     }
663    
664     if (abs(new_scale - scale) < 2) {
665     return; // Smoothing
666     }
667    
668     if (new_scale >= this_->autozoom_min) {
669     navit_scale(this_, (long)new_scale, &pc, 0);
670     } else {
671     if (scale != this_->autozoom_min) {
672     navit_scale(this_, this_->autozoom_min, &pc, 0);
673     }
674     }
675     }
676    
677     /**
678     * Change the current zoom level, zooming closer to the ground
679     *
680     * @param navit The navit instance
681     * @param factor The zoom factor, usually 2
682     * @param p The invariant point (if set to NULL, default to center)
683     * @returns nothing
684     */
685     void
686     navit_zoom_in(struct navit *this_, int factor, struct point *p)
687     {
688     //dbg(0,"EEnter\n");
689     long scale=transform_get_scale(this_->trans)/factor;
690     if (scale < 1)
691     scale=1;
692     //dbg(0,"zoom in -> scale=%d",scale);
693     navit_scale(this_, scale, p, 1);
694     }
695    
696     /**
697     * Change the current zoom level
698     *
699     * @param navit The navit instance
700     * @param factor The zoom factor, usually 2
701     * @param p The invariant point (if set to NULL, default to center)
702     * @returns nothing
703     */
704     void
705     navit_zoom_out(struct navit *this_, int factor, struct point *p)
706     {
707     //dbg(0,"EEnter\n");
708     long scale=transform_get_scale(this_->trans)*factor;
709     //dbg(0,"zoom out -> scale=%d",scale);
710     navit_scale(this_, scale, p, 1);
711     }
712    
713     int
714     navit_get_cur_pnt(struct navit *this_, struct point *p)
715     {
716     //dbg(0,"EEnter\n");
717     return navit_get_cursor_pnt(this_, p, 0, NULL);
718     }
719    
720     void
721     navit_zoom_in_cursor(struct navit *this_, int factor)
722     {
723     //dbg(0,"EEnter\n");
724     struct point p;
725     if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) {
726     navit_zoom_in(this_, factor, &p);
727     this_->vehicle->follow_curr=this_->vehicle->follow;
728     } else
729     navit_zoom_in(this_, factor, NULL);
730     }
731    
732     void
733     navit_zoom_to_scale(struct navit *this_, int new_scale)
734     {
735     //dbg(0,"EEnter\n");
736     long scale=transform_get_scale(this_->trans);
737     long new_scale_long=new_scale;
738     //dbg(0,"zoom to scale -> old scale=%d",scale);
739     //dbg(0,"zoom to scale -> want scale=%d",new_scale_long);
740    
741     // only do something if scale changed!
742     if (scale != new_scale_long)
743     {
744     navit_scale(this_, new_scale_long, NULL, 1);
745     }
746     }
747    
748     void
749     navit_zoom_out_cursor(struct navit *this_, int factor)
750     {
751     //dbg(0,"EEnter\n");
752     struct point p;
753     if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) {
754     navit_zoom_out(this_, 2, &p);
755     this_->vehicle->follow_curr=this_->vehicle->follow;
756     } else
757     navit_zoom_out(this_, 2, NULL);
758     }
759    
760     static int
761     navit_cmd_zoom_in(struct navit *this_)
762     {
763     //dbg(0,"EEnter\n");
764     navit_zoom_in_cursor(this_, 2);
765     return 0;
766     }
767    
768     static int
769     navit_cmd_zoom_out(struct navit *this_)
770     {
771     //dbg(0,"EEnter\n");
772     navit_zoom_out_cursor(this_, 2);
773     return 0;
774     }
775    
776    
777     static void
778     navit_cmd_say(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
779     {
780     //dbg(0,"EEnter\n");
781     if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str)
782     navit_say(this, in[0]->u.str);
783     }
784    
785     static GHashTable *cmd_int_var_hash = NULL;
786     static GHashTable *cmd_attr_var_hash = NULL;
787    
788     /**
789     * Store key value pair for the command system (for int typed values)
790     *
791     * @param navit The navit instance
792     * @param function unused (needed to match command function signiture)
793     * @param in input attributes in[0] is the key string, in[1] is the integer value to store
794     * @param out output attributes, unused
795     * @param valid unused
796     * @returns nothing
797     */
798     static void
799     navit_cmd_set_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
800     {
801     //dbg(0,"EEnter\n");
802     char*key;
803     struct attr*val;
804     if(!cmd_int_var_hash) {
805     cmd_int_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
806     }
807    
808     if ( (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) &&
809     (in && in[1] && ATTR_IS_NUMERIC(in[1]->type))) {
810     val = g_new(struct attr,1);
811     attr_dup_content(in[1],val);
812     key = g_strdup(in[0]->u.str);
813     g_hash_table_insert(cmd_int_var_hash, key, val);
814     }
815     }
816    
817    
818     /**
819     * Store key value pair for the command system (for attr typed values, can be used as opaque handles)
820     *
821     * @param navit The navit instance
822     * @param function unused (needed to match command function signiture)
823     * @param in input attributes in[0] is the key string, in[1] is the attr* value to store
824     * @param out output attributes, unused
825     * @param valid unused
826     * @returns nothing
827     */
828     //TODO free stored attributes on navit_destroy
829     static void
830     navit_cmd_set_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
831     {
832     //dbg(0,"EEnter\n");
833     char*key;
834     struct attr*val;
835     if(!cmd_attr_var_hash) {
836     cmd_attr_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
837     }
838    
839     if ( (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) &&
840     (in && in[1] )) {
841     val = attr_dup(in[1]);
842     //val = in[1];
843     key = g_strdup(in[0]->u.str);
844     g_hash_table_insert(cmd_attr_var_hash, key, val);
845     }
846     }
847    
848    
849    
850     /**
851     * command to toggle the active state of a named layer of the current layout
852     *
853     * @param navit The navit instance
854     * @param function unused (needed to match command function signiture)
855     * @param in input attribute in[0] is the name of the layer
856     * @param out output unused
857     * @param valid unused
858     * @returns nothing
859     */
860     static void
861     navit_cmd_toggle_layer(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
862     {
863     //dbg(0,"EEnter\n");
864     if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
865     if(this->layout_current && this->layout_current->layers) {
866     GList* layers = this->layout_current->layers;
867     while (layers) {
868     struct layer*l=layers->data;
869     if(l && !strcmp(l->name,in[0]->u.str) ) {
870     l->active ^= 1;
871     navit_draw(this);
872     return;
873     }
874     layers=g_list_next(layers);
875     }
876     }
877     }
878     }
879    
880     /**
881     * adds an item with the current coordinate of the vehicle to a named map
882     *
883     * @param navit The navit instance
884     * @param function unused (needed to match command function signiture)
885     * @param in input attribute in[0] is the name of the map
886     * @param out output attribute, 0 on error or the id of the created item on success
887     * @param valid unused
888     * @returns nothing
889     */
890     static void
891     navit_cmd_map_add_curr_pos(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
892     {
893     //dbg(0,"EEnter\n");
894     struct attr **list = g_new0(struct attr *,2);
895     struct attr*val = g_new0(struct attr,1);
896     struct mapset* ms;
897     struct map_selection sel;
898     const int selection_range = 10;
899     enum item_type item_type;
900     struct item *it;
901     struct map* curr_map = NULL;
902     struct coord curr_coord;
903     struct map_rect *mr;
904    
905     val->type = attr_type_item_begin;
906     val->u.item = NULL; //return invalid item on error
907     list[0] = val;
908     list[1] = NULL;
909     *out = list;
910     if (
911     in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str && //map name
912     in[1] && ATTR_IS_STRING(in[1]->type) && in[1]->u.str //item type
913     ) {
914    
915     if(!(ms=navit_get_mapset(this))) {
916     return;
917     }
918    
919     if((item_type = item_from_name(in[1]->u.str))==type_none) {
920     return;
921     }
922    
923     curr_map = mapset_get_map_by_name(ms, in[0]->u.str);
924    
925     //no map with the given name found
926     if( ! curr_map) {
927     return;
928     }
929    
930     if(this->vehicle && this->vehicle->vehicle ) {
931     struct attr pos_attr;
932     if(vehicle_get_attr(this->vehicle->vehicle,attr_position_coord_geo,&pos_attr,NULL)) {
933     transform_from_geo(projection_mg, pos_attr.u.coord_geo, &curr_coord);
934     } else {
935     return;
936     }
937     } else {
938     return;
939     }
940    
941     sel.next=NULL;
942     sel.order=18;
943     sel.range.min=type_none;
944     sel.range.max=type_tec_common;
945     sel.u.c_rect.lu.x=curr_coord.x-selection_range;
946     sel.u.c_rect.lu.y=curr_coord.y+selection_range;
947     sel.u.c_rect.rl.x=curr_coord.x+selection_range;
948     sel.u.c_rect.rl.y=curr_coord.y-selection_range;
949    
950     mr = map_rect_new(curr_map, &sel);
951     if(mr) {
952     it = map_rect_create_item( mr, item_type);
953     item_coord_set(it,&curr_coord, 1, change_mode_modify);
954     val->u.item = it;
955     }
956     map_rect_destroy(mr);
957     }
958     }
959    
960     /**
961     * sets an attribute (name value pair) of a map item specified by map name and item id
962     *
963     * @param navit The navit instance
964     * @param function unused (needed to match command function signiture)
965     * @param in input attribute in[0] - name of the map ; in[1] - item ; in[2] - attr name ; in[3] - attr value
966     * @param out output attribute, 0 on error, 1 on success
967     * @param valid unused
968     * @returns nothing
969     */
970     static void
971     navit_cmd_map_item_set_attr(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
972     {
973     //dbg(0,"EEnter\n");
974     if (
975     in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str &&//map name
976     in[1] && ATTR_IS_ITEM(in[1]->type) && //item
977     in[2] && ATTR_IS_STRING(in[2]->type) && in[2]->u.str && //attr_type str
978     in[3] && ATTR_IS_STRING(in[3]->type) && in[3]->u.str //attr_value str
979     ) {
980     struct attr attr_to_set;
981     struct map* curr_map = NULL;
982     struct mapset *ms;
983     struct map_selection sel;
984     const int selection_range = 500;
985     struct coord curr_coord;
986     struct item *it;
987    
988     if(ATTR_IS_STRING(attr_from_name(in[2]->u.str))) {
989     attr_to_set.u.str = in[3]->u.str;
990     attr_to_set.type = attr_from_name(in[2]->u.str);
991     }
992     else if(ATTR_IS_INT(attr_from_name(in[2]->u.str))) {
993     attr_to_set.u.num = atoi(in[3]->u.str);
994     attr_to_set.type = attr_from_name(in[2]->u.str);
995     }
996     else if(ATTR_IS_DOUBLE(attr_from_name(in[2]->u.str))) {
997     double* val = g_new0(double,1);
998     *val = atof(in[3]->u.str);
999     attr_to_set.u.numd = val;
1000     attr_to_set.type = attr_from_name(in[2]->u.str);
1001     }
1002    
1003     ms = navit_get_mapset(this);
1004    
1005     curr_map = mapset_get_map_by_name(ms, in[0]->u.str);
1006    
1007     if( ! curr_map) {
1008     return;
1009     }
1010     sel.next=NULL;
1011     sel.order=18;
1012     sel.range.min=type_none;
1013     sel.range.max=type_tec_common;
1014     sel.u.c_rect.lu.x=curr_coord.x-selection_range;
1015     sel.u.c_rect.lu.y=curr_coord.y+selection_range;
1016     sel.u.c_rect.rl.x=curr_coord.x+selection_range;
1017     sel.u.c_rect.rl.y=curr_coord.y-selection_range;
1018    
1019     it = in[1]->u.item;
1020     if(it) {
1021     item_attr_set(it, &attr_to_set, change_mode_modify);
1022     }
1023     }
1024     }
1025    
1026     /**
1027     * Get attr variable given a key string for the command system (for opaque usage)
1028     *
1029     * @param navit The navit instance
1030     * @param function unused (needed to match command function signiture)
1031     * @param in input attribute in[0] is the key string
1032     * @param out output attribute, the attr for the given key string if exists or NULL
1033     * @param valid unused
1034     * @returns nothing
1035     */
1036     static void
1037     navit_cmd_get_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1038     {
1039     //dbg(0,"EEnter\n");
1040     struct attr **list = g_new0(struct attr *,2);
1041     if(!cmd_int_var_hash) {
1042     struct attr*val = g_new0(struct attr,1);
1043     val->type = attr_type_item_begin;
1044     val->u.item = NULL;
1045     list[0] = val;
1046     }
1047     if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
1048     struct attr*ret = g_hash_table_lookup(cmd_attr_var_hash, in[0]->u.str);
1049     if(ret) {
1050     list[0] = attr_dup(ret);
1051     }
1052     else {
1053     struct attr*val = g_new0(struct attr,1);
1054     val->type = attr_type_int_begin;
1055     val->u.item = NULL;
1056     list[0] = val;
1057     }
1058     }
1059     list[1] = NULL;
1060     *out = list;
1061     }
1062    
1063    
1064     /**
1065     * Get value given a key string for the command system
1066     *
1067     * @param navit The navit instance
1068     * @param function unused (needed to match command function signiture)
1069     * @param in input attribute in[0] is the key string
1070     * @param out output attribute, the value for the given key string if exists or 0
1071     * @param valid unused
1072     * @returns nothing
1073     */
1074     static void
1075     navit_cmd_get_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1076     {
1077     //dbg(0,"EEnter\n");
1078     struct attr **list = g_new0(struct attr *,2);
1079     if(!cmd_int_var_hash) {
1080     struct attr*val = g_new0(struct attr,1);
1081     val->type = attr_type_int_begin;
1082     val->u.num = 0;
1083     list[0] = val;
1084     }
1085     if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
1086     struct attr*ret = g_hash_table_lookup(cmd_int_var_hash, in[0]->u.str);
1087     if(ret) {
1088     list[0] = ret;
1089     }
1090     else {
1091     struct attr*val = g_new0(struct attr,1);
1092     val->type = attr_type_int_begin;
1093     val->u.num = 0;
1094     list[0] = val;
1095     }
1096     }
1097     list[1] = NULL;
1098     *out = list;
1099     }
1100    
1101     GList *cmd_int_var_stack = NULL;
1102    
1103     /**
1104     * Push an integer to the stack for the command system
1105     *
1106     * @param navit The navit instance
1107     * @param function unused (needed to match command function signiture)
1108     * @param in input attribute in[0] is the integer attibute to push
1109     * @param out output attributes, unused
1110     * @param valid unused
1111     * @returns nothing
1112     */
1113     static void
1114     navit_cmd_push_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1115     {
1116     //dbg(0,"EEnter\n");
1117     if (in && in[0] && ATTR_IS_NUMERIC(in[0]->type)) {
1118     struct attr*val = g_new(struct attr,1);
1119     attr_dup_content(in[0],val);
1120     cmd_int_var_stack = g_list_prepend(cmd_int_var_stack, val);
1121     }
1122     }
1123    
1124     /**
1125     * Pop an integer from the command system's integer stack
1126     *
1127     * @param navit The navit instance
1128     * @param function unused (needed to match command function signiture)
1129     * @param in input attributes unused
1130     * @param out output attribute, the value popped if stack isn't empty or 0
1131     * @param valid unused
1132     * @returns nothing
1133     */
1134     static void
1135     navit_cmd_pop_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1136     {
1137     //dbg(0,"EEnter\n");
1138     struct attr **list = g_new0(struct attr *,2);
1139     if(!cmd_int_var_stack) {
1140     struct attr*val = g_new0(struct attr,1);
1141     val->type = attr_type_int_begin;
1142     val->u.num = 0;
1143     list[0] = val;
1144     }
1145     else {
1146     list[0] = cmd_int_var_stack->data;
1147     cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack,cmd_int_var_stack);
1148     }
1149     list[1] = NULL;
1150     *out = list;
1151     }
1152    
1153     /**
1154     * Get current size of command system's integer stack
1155     *
1156     * @param navit The navit instance
1157     * @param function unused (needed to match command function signiture)
1158     * @param in input attributes unused
1159     * @param out output attribute, the size of stack
1160     * @param valid unused
1161     * @returns nothing
1162     */
1163     static void
1164     navit_cmd_int_stack_size(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1165     {
1166     //dbg(0,"EEnter\n");
1167     struct attr **list;
1168     struct attr *attr = g_new0(struct attr ,1);
1169     attr->type = attr_type_int_begin;
1170     if(!cmd_int_var_stack) {
1171     attr->u.num = 0;
1172     }
1173     else {
1174     attr->u.num = g_list_length(cmd_int_var_stack);
1175     }
1176     list = g_new0(struct attr *,2);
1177     list[0] = attr;
1178     list[1] = NULL;
1179     *out = list;
1180     cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack,cmd_int_var_stack);
1181     }
1182    
1183     static void
1184     navit_cmd_set_destination(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1185     {
1186     //dbg(0,"EEnter\n");
1187     struct pcoord pc;
1188     char *description=NULL;
1189     if (!in)
1190     return;
1191     if (!in[0])
1192     return;
1193     pc.pro = transform_get_projection(this->trans);
1194     if (ATTR_IS_COORD(in[0]->type)) {
1195     pc.x=in[0]->u.coord->x;
1196     pc.y=in[0]->u.coord->y;
1197     in++;
1198     } else if (ATTR_IS_PCOORD(in[0]->type)) {
1199     pc=*in[0]->u.pcoord;
1200     in++;
1201     } else if (in[1] && in[2] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type) && ATTR_IS_INT(in[2]->type)) {
1202     pc.pro=in[0]->u.num;
1203     pc.x=in[1]->u.num;
1204     pc.y=in[2]->u.num;
1205     in+=3;
1206     } else if (in[1] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type)) {
1207     pc.x=in[0]->u.num;
1208     pc.y=in[1]->u.num;
1209     in+=2;
1210     } else
1211     return;
1212     if (in[0] && ATTR_IS_STRING(in[0]->type))
1213     description=in[0]->u.str;
1214     navit_set_destination(this, &pc, description, 1);
1215     }
1216    
1217     static void
1218     navit_cmd_fmt_coordinates(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1219     {
1220     //dbg(0,"EEnter\n");
1221     struct attr attr;
1222     attr.type=attr_type_string_begin;
1223     attr.u.str="Fix me";
1224     if (out) {
1225     *out=attr_generic_add_attr(*out, &attr);
1226     }
1227     }
1228    
1229     /**
1230     * Join several string attributes into one
1231     *
1232     * @param navit The navit instance
1233     * @param function unused (needed to match command function signiture)
1234     * @param in input attributes in[0] - separator, in[1..] - attributes to join
1235     * @param out output attribute joined attribute as string
1236     * @param valid unused
1237     * @returns nothing
1238     */
1239     static void
1240     navit_cmd_strjoin(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1241     {
1242     //dbg(0,"EEnter\n");
1243     struct attr attr;
1244     gchar *ret, *sep;
1245     int i;
1246     attr.type=attr_type_string_begin;
1247     attr.u.str=NULL;
1248     if(in[0] && in[1]) {
1249     sep=attr_to_text(in[0],NULL,1);
1250     ret=attr_to_text(in[1],NULL,1);
1251     for(i=2;in[i];i++) {
1252     gchar *in_i=attr_to_text(in[i],NULL,1);
1253     gchar *r=g_strjoin(sep,ret,in_i,NULL);
1254     g_free(in_i);
1255     g_free(ret);
1256     ret=r;
1257     }
1258     g_free(sep);
1259     attr.u.str=ret;
1260     if(out) {
1261     *out=attr_generic_add_attr(*out, &attr);
1262     }
1263     g_free(ret);
1264     }
1265     }
1266    
1267     /**
1268     * Call external program
1269     *
1270     * @param navit The navit instance
1271     * @param function unused (needed to match command function signiture)
1272     * @param in input attributes in[0] - name of executable, in[1..] - parameters
1273     * @param out output attribute unused
1274     * @param valid unused
1275     * @returns nothing
1276     */
1277     static void
1278     navit_cmd_spawn(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
1279     {
1280     //dbg(0,"EEnter\n");
1281     int i,j, nparms, nvalid;
1282     const char ** argv=NULL;
1283     struct spawn_process_info *pi;
1284    
1285     nparms=0;
1286     nvalid=0;
1287     if(in) {
1288     while(in[nparms]) {
1289     if (in[nparms]->type!=attr_none)
1290     nvalid++;
1291     nparms++;
1292     }
1293     }
1294    
1295     if(nvalid>0) {
1296     argv=g_new(char*,nvalid+1);
1297     for(i=0,j=0;in[i];i++) {
1298     if(in[i]->type!=attr_none ) {
1299     argv[j++]=attr_to_text(in[i],NULL,1);
1300     } else {
1301     dbg(0,"Parameter #%i is attr_none - skipping\n",i);
1302     }
1303     }
1304     argv[j]=NULL;
1305     pi=spawn_process(argv);
1306    
1307     // spawn_process() testing suite - uncomment following code to test.
1308     //sleep(3);
1309     // example of non-blocking wait
1310     //int st=spawn_process_check_status(pi,0);dbg(0,"status %i\n",st);
1311     // example of blocking wait
1312     //st=spawn_process_check_status(pi,1);dbg(0,"status %i\n",st);
1313     // example of wait after process is finished and status is
1314     // already tested
1315     //st=spawn_process_check_status(pi,1);dbg(0,"status %i\n",st);
1316     // example of wait after process is finished and status is
1317     // already tested - unblocked
1318     //st=spawn_process_check_status(pi,0);dbg(0,"status %i\n",st);
1319    
1320     // End testing suite
1321     spawn_process_info_free(pi);
1322     for(i=0;argv[i];i++)
1323     g_free(argv[i]);
1324     g_free(argv);
1325     }
1326     }
1327    
1328    
1329     static struct command_table commands[] = {
1330     {"zoom_in",command_cast(navit_cmd_zoom_in)},
1331     {"zoom_out",command_cast(navit_cmd_zoom_out)},
1332     {"zoom_to_route",command_cast(navit_cmd_zoom_to_route)},
1333     {"say",command_cast(navit_cmd_say)},
1334     {"set_center_cursor",command_cast(navit_cmd_set_center_cursor)},
1335     {"set_destination",command_cast(navit_cmd_set_destination)},
1336     {"announcer_toggle",command_cast(navit_cmd_announcer_toggle)},
1337     {"fmt_coordinates",command_cast(navit_cmd_fmt_coordinates)},
1338     {"set_int_var",command_cast(navit_cmd_set_int_var)},
1339     {"get_int_var",command_cast(navit_cmd_get_int_var)},
1340     {"push_int",command_cast(navit_cmd_push_int)},
1341     {"pop_int",command_cast(navit_cmd_pop_int)},
1342     {"int_stack_size",command_cast(navit_cmd_int_stack_size)},
1343     {"toggle_layer",command_cast(navit_cmd_toggle_layer)},
1344     {"strjoin",command_cast(navit_cmd_strjoin)},
1345     {"spawn",command_cast(navit_cmd_spawn)},
1346     {"map_add_curr_pos",command_cast(navit_cmd_map_add_curr_pos)},
1347     {"map_item_set_attr",command_cast(navit_cmd_map_item_set_attr)},
1348     {"set_attr_var",command_cast(navit_cmd_set_attr_var)},
1349     {"get_attr_var",command_cast(navit_cmd_get_attr_var)},
1350     };
1351    
1352     void
1353     navit_command_add_table(struct navit*this_, struct command_table *commands, int count)
1354     {
1355     //dbg(0,"EEnter\n");
1356     command_add_table(this_->attr_cbl, commands, count, this_);
1357     }
1358    
1359     struct navit *
1360     navit_new(struct attr *parent, struct attr **attrs)
1361     {
1362     //dbg(0,"EEnter\n");
1363     struct navit *this_=g_new0(struct navit, 1);
1364     struct pcoord center;
1365     struct coord co;
1366     struct coord_geo g;
1367     enum projection pro=projection_mg;
1368     int zoom = 256;
1369     g.lat=53.13;
1370     g.lng=11.70;
1371    
1372     this_->self.type=attr_navit;
1373     this_->self.u.navit=this_;
1374     this_->attr_cbl=callback_list_new();
1375    
1376     this_->orientation=-1;
1377     this_->tracking_flag=1;
1378     this_->recentdest_count=10;
1379     this_->osd_configuration=-1;
1380    
1381     // changed default to 1
1382     this_->center_timeout = 1;
1383     this_->use_mousewheel = 1;
1384     this_->autozoom_secs = 10;
1385     this_->autozoom_min = 7;
1386     this_->autozoom_active = 0;
1387     this_->zoom_min = 1;
1388     this_->zoom_max = 1048576; //-> order=-2 // 2097152 -> order=-3;
1389     this_->follow_cursor = 1;
1390     this_->radius = 30;
1391     this_->border = 16;
1392    
1393     this_->trans = transform_new();
1394     this_->trans_cursor = transform_new();
1395     transform_from_geo(pro, &g, &co);
1396     center.x=co.x;
1397     center.y=co.y;
1398     center.pro = pro;
1399    
1400     dbg(0,"setting center from xmlfile [hardcoded]\n");
1401     transform_setup(this_->trans, &center, zoom, (this_->orientation != -1) ? this_->orientation : 0);
1402    
1403     // initialze trans_cursor here
1404     transform_copy(this_->trans, this_->trans_cursor);
1405     // initialze trans_cursor here
1406    
1407     this_->bookmarks=bookmarks_new(&this_->self, NULL, this_->trans);
1408    
1409     this_->prevTs=0;
1410    
1411     for (;*attrs; attrs++) {
1412     navit_set_attr_do(this_, *attrs, 1);
1413     }
1414     this_->displaylist=graphics_displaylist_new();
1415     command_add_table(this_->attr_cbl, commands, sizeof(commands)/sizeof(struct command_table), this_);
1416    
1417     this_->messages = messagelist_new(attrs);
1418    
1419     //dbg(0,"111111\n");
1420    
1421     return this_;
1422     }
1423    
1424     static int
1425     navit_set_gui(struct navit *this_, struct gui *gui)
1426     {
1427     //dbg(0,"EEnter\n");
1428     if (this_->gui)
1429     return 0;
1430     this_->gui=gui;
1431     if (gui_has_main_loop(this_->gui)) {
1432     if (! main_loop_gui) {
1433     main_loop_gui=this_->gui;
1434     } else {
1435     dbg(0,"gui with main loop already active, ignoring this instance");
1436     return 0;
1437     }
1438     }
1439     return 1;
1440     }
1441    
1442     void
1443     navit_add_message(struct navit *this_, char *message)
1444     {
1445     //dbg(0,"EEnter\n");
1446     message_new(this_->messages, message);
1447     }
1448    
1449     struct message
1450     *navit_get_messages(struct navit *this_)
1451     {
1452     //dbg(0,"EEnter\n");
1453     return message_get(this_->messages);
1454     }
1455    
1456     static int
1457     navit_set_graphics(struct navit *this_, struct graphics *gra)
1458     {
1459     //dbg(0,"EEnter\n");
1460     if (this_->gra)
1461     return 0;
1462     this_->gra=gra;
1463     this_->resize_callback=callback_new_attr_1(callback_cast(navit_resize), attr_resize, this_);
1464     graphics_add_callback(gra, this_->resize_callback);
1465     this_->button_callback=callback_new_attr_1(callback_cast(navit_button), attr_button, this_);
1466     graphics_add_callback(gra, this_->button_callback);
1467     this_->motion_callback=callback_new_attr_1(callback_cast(navit_motion), attr_motion, this_);
1468     graphics_add_callback(gra, this_->motion_callback);
1469     this_->predraw_callback=callback_new_attr_1(callback_cast(navit_predraw), attr_predraw, this_);
1470     graphics_add_callback(gra, this_->predraw_callback);
1471     //dbg(0,"111111111\n");
1472     return 1;
1473     }
1474    
1475     struct graphics *
1476     navit_get_graphics(struct navit *this_)
1477     {
1478     //dbg(0,"EEnter\n");
1479     return this_->gra;
1480     }
1481    
1482     struct vehicleprofile *
1483     navit_get_vehicleprofile(struct navit *this_)
1484     {
1485     //dbg(0,"EEnter\n");
1486     return this_->vehicleprofile;
1487     }
1488    
1489     GList *
1490     navit_get_vehicleprofiles(struct navit *this_)
1491     {
1492     //dbg(0,"EEnter\n");
1493     return this_->vehicleprofiles;
1494     }
1495    
1496     static void
1497     navit_projection_set(struct navit *this_, enum projection pro, int draw)
1498     {
1499     //dbg(0,"EEnter\n");
1500     struct coord_geo g;
1501     struct coord *c;
1502    
1503     c=transform_center(this_->trans);
1504     transform_to_geo(transform_get_projection(this_->trans), c, &g);
1505     transform_set_projection(this_->trans, pro);
1506     transform_from_geo(pro, &g, c);
1507     if (draw)
1508     navit_draw(this_);
1509     }
1510    
1511     /**
1512     * Start the route computing to a given set of coordinates
1513     *
1514     * @param navit The navit instance
1515     * @param c The coordinate to start routing to
1516     * @param description A label which allows the user to later identify this destination in the former destinations selection
1517     * @returns nothing
1518     */
1519     void
1520     navit_set_destination(struct navit *this_, struct pcoord *c, const char *description, int async)
1521     {
1522     //dbg(0,"EEnter\n");
1523     char *destination_file;
1524     if (c) {
1525     this_->destination=*c;
1526     this_->destination_valid=1;
1527    
1528     dbg(1, "navit->navit_set_destination %i\n", c->x);
1529     dbg(1, "navit->navit_set_destination %i\n", c->y);
1530    
1531     } else
1532     this_->destination_valid=0;
1533     destination_file = bookmarks_get_destination_file(TRUE);
1534     bookmarks_append_coord(this_->bookmarks, destination_file, c, 1, "former_destination", description, NULL, this_->recentdest_count);
1535     g_free(destination_file);
1536     callback_list_call_attr_0(this_->attr_cbl, attr_destination);
1537     if (this_->route) {
1538     route_set_destination(this_->route, c, async);
1539    
1540     if (this_->ready == 3)
1541     navit_draw(this_);
1542     }
1543     }
1544    
1545     /**
1546     * Start the route computing to a given set of coordinates including waypoints
1547     *
1548     * @param navit The navit instance
1549     * @param c The coordinate to start routing to
1550     * @param description A label which allows the user to later identify this destination in the former destinations selection
1551     * @returns nothing
1552     */
1553     void
1554     navit_set_destinations(struct navit *this_, struct pcoord *c, int count, const char *description, int async)
1555     {
1556     //dbg(0,"EEnter\n");
1557     char *destination_file;
1558     if (c && count) {
1559     this_->destination=c[count-1];
1560     this_->destination_valid=1;
1561     } else
1562     this_->destination_valid=0;
1563     destination_file = bookmarks_get_destination_file(TRUE);
1564     bookmarks_append_coord(this_->bookmarks, destination_file, c, count, "former_itinerary", description, NULL, this_->recentdest_count);
1565     g_free(destination_file);
1566     callback_list_call_attr_0(this_->attr_cbl, attr_destination);
1567     if (this_->route) {
1568     route_set_destinations(this_->route, c, count, async);
1569    
1570     if (this_->ready == 3)
1571     navit_draw(this_);
1572     }
1573     }
1574    
1575     /**
1576     * @brief Checks if a route is calculated
1577     *
1578     * This function checks if a route is calculated.
1579     *
1580     * @param this_ The navit struct whose route should be checked.
1581     * @return True if the route is set, false otherwise.
1582     */
1583     int
1584     navit_check_route(struct navit *this_)
1585     {
1586     //dbg(0,"EEnter\n");
1587     if (this_->route) {
1588     return route_get_path_set(this_->route);
1589     }
1590    
1591     return 0;
1592     }
1593    
1594     static int
1595     navit_former_destinations_active(struct navit *this_)
1596     {
1597     //dbg(0,"EEnter\n");
1598     char *destination_file = bookmarks_get_destination_file(FALSE);
1599     FILE *f;
1600     int active=0;
1601     char buffer[3];
1602     f=fopen(destination_file,"r");
1603     if (f) {
1604     if(!fseek(f, -2, SEEK_END) && fread(buffer, 2, 1, f) == 1 && (buffer[0]!='\n' || buffer[1]!='\n'))
1605     active=1;
1606     fclose(f);
1607     }
1608     g_free(destination_file);
1609     return active;
1610     }
1611    
1612     static void
1613     navit_add_former_destinations_from_file(struct navit *this_)
1614     {
1615     //dbg(0,"EEnter\n");
1616     char *destination_file = bookmarks_get_destination_file(FALSE);
1617     struct attr *attrs[4];
1618     struct map_rect *mr;
1619     struct item *item;
1620     int i,valid=0,count=0;
1621     struct coord c[16];
1622     struct pcoord pc[16];
1623     struct attr parent;
1624     struct attr type;
1625     struct attr data;
1626     struct attr flags;
1627    
1628     parent.type=attr_navit;
1629     parent.u.navit=this_;
1630    
1631     type.type=attr_type;
1632     type.u.str="textfile";
1633    
1634     data.type=attr_data;
1635     data.u.str=destination_file;
1636    
1637     flags.type=attr_flags;
1638     flags.u.num=1;
1639    
1640     attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
1641    
1642     this_->former_destination=map_new(&parent, attrs);
1643     g_free(destination_file);
1644     if (!this_->route || !navit_former_destinations_active(this_))
1645     return;
1646     mr=map_rect_new(this_->former_destination, NULL);
1647     while ((item=map_rect_get_item(mr))) {
1648     if ((item->type == type_former_destination || item->type == type_former_itinerary || item->type == type_former_itinerary_part) && (count=item_coord_get(item, c, 16)))
1649     valid=1;
1650     }
1651     map_rect_destroy(mr);
1652     if (valid && count > 0) {
1653     for (i = 0 ; i < count ; i++) {
1654     pc[i].pro=map_projection(this_->former_destination);
1655     pc[i].x=c[i].x;
1656     pc[i].y=c[i].y;
1657     }
1658     if (count == 1)
1659     route_set_destination(this_->route, &pc[0], 1);
1660     else
1661     route_set_destinations(this_->route, pc, count, 1);
1662     this_->destination=pc[count-1];
1663     this_->destination_valid=1;
1664     }
1665     }
1666    
1667    
1668     void
1669     navit_textfile_debug_log(struct navit *this_, const char *fmt, ...)
1670     {
1671     //dbg(0,"EEnter\n");
1672     va_list ap;
1673     char *str1,*str2;
1674     va_start(ap, fmt);
1675     if (this_->textfile_debug_log && this_->vehicle) {
1676     str1=g_strdup_vprintf(fmt, ap);
1677     str2=g_strdup_printf("0x%x 0x%x%s%s\n", this_->vehicle->coord.x, this_->vehicle->coord.y, strlen(str1) ? " " : "", str1);
1678     log_write(this_->textfile_debug_log, str2, strlen(str2), 0);
1679     g_free(str2);
1680     g_free(str1);
1681     }
1682     va_end(ap);
1683     }
1684    
1685     void
1686     navit_textfile_debug_log_at(struct navit *this_, struct pcoord *pc, const char *fmt, ...)
1687     {
1688     //dbg(0,"EEnter\n");
1689     va_list ap;
1690     char *str1,*str2;
1691     va_start(ap, fmt);
1692     if (this_->textfile_debug_log && this_->vehicle) {
1693     str1=g_strdup_vprintf(fmt, ap);
1694     str2=g_strdup_printf("0x%x 0x%x%s%s\n", pc->x, pc->y, strlen(str1) ? " " : "", str1);
1695     log_write(this_->textfile_debug_log, str2, strlen(str2), 0);
1696     g_free(str2);
1697     g_free(str1);
1698     }
1699     va_end(ap);
1700     }
1701    
1702     void
1703     navit_say(struct navit *this_, char *text)
1704     {
1705     //dbg(0,"EEnter\n");
1706     if(this_->speech) {
1707     speech_say(this_->speech, text);
1708     }
1709     }
1710    
1711     /**
1712     * @brief Toggles the navigation announcer for navit
1713     * @param this_ The navit object
1714     */
1715     static void
1716     navit_cmd_announcer_toggle(struct navit *this_)
1717     {
1718     struct attr attr, speechattr;
1719    
1720     // search for the speech attribute
1721     if(!navit_get_attr(this_, attr_speech, &speechattr, NULL))
1722     return;
1723     // find out if the corresponding attribute attr_active has been set
1724     if(speech_get_attr(speechattr.u.speech, attr_active, &attr, NULL)) {
1725     // flip it then...
1726     attr.u.num = !attr.u.num;
1727     } else {
1728     // otherwise disable it because voice is enabled by default
1729     attr.type = attr_active;
1730     attr.u.num = 0;
1731     }
1732    
1733     // apply the new state
1734     if(!speech_set_attr(speechattr.u.speech, &attr))
1735     return;
1736    
1737     // announce that the speech attribute has changed
1738     callback_list_call_attr_0(this_->attr_cbl, attr_speech);
1739     }
1740    
1741    
1742    
1743    
1744     void
1745     navit_cmd_announcer_on(struct navit *this_)
1746     {
1747     struct attr attr, speechattr;
1748    
1749     // search for the speech attribute
1750     if(!navit_get_attr(this_, attr_speech, &speechattr, NULL))
1751     return;
1752    
1753     attr.type = attr_active;
1754     attr.u.num = 1;
1755    
1756     // apply the new state
1757     if(!speech_set_attr(speechattr.u.speech, &attr))
1758     return;
1759    
1760     // announce that the speech attribute has changed
1761     callback_list_call_attr_0(this_->attr_cbl, attr_speech);
1762     }
1763    
1764    
1765     void
1766     navit_cmd_announcer_off(struct navit *this_)
1767     {
1768     struct attr attr, speechattr;
1769    
1770     // search for the speech attribute
1771     if(!navit_get_attr(this_, attr_speech, &speechattr, NULL))
1772     return;
1773    
1774     attr.type = attr_active;
1775     attr.u.num = 0;
1776    
1777     // apply the new state
1778     if(!speech_set_attr(speechattr.u.speech, &attr))
1779     return;
1780    
1781     // announce that the speech attribute has changed
1782     callback_list_call_attr_0(this_->attr_cbl, attr_speech);
1783     }
1784    
1785    
1786    
1787     void
1788     navit_speak(struct navit *this_)
1789     {
1790     //dbg(0,"EEnter\n");
1791     struct navigation *nav=this_->navigation;
1792     struct map *map=NULL;
1793     struct map_rect *mr=NULL;
1794     struct item *item;
1795     struct attr attr;
1796    
1797     if (!speech_get_attr(this_->speech, attr_active, &attr, NULL))
1798     attr.u.num = 1;
1799     dbg(1, "this_.speech->active %i\n", attr.u.num);
1800     if(!attr.u.num)
1801     return;
1802    
1803     if (nav)
1804     map=navigation_get_map(nav);
1805     if (map)
1806     mr=map_rect_new(map, NULL);
1807     if (mr) {
1808     while ((item=map_rect_get_item(mr)) && (item->type == type_nav_position || item->type == type_nav_none));
1809     if (item && item_attr_get(item, attr_navigation_speech, &attr)) {
1810     speech_say(this_->speech, attr.u.str);
1811     navit_add_message(this_, attr.u.str);
1812     navit_textfile_debug_log(this_, "type=announcement label=\"%s\"", attr.u.str);
1813     }
1814     map_rect_destroy(mr);
1815     }
1816     }
1817    
1818     static void
1819     navit_window_roadbook_update(struct navit *this_)
1820     {
1821     //dbg(0,"EEnter\n");
1822     struct navigation *nav=this_->navigation;
1823     struct map *map=NULL;
1824     struct map_rect *mr=NULL;
1825     struct item *item;
1826     struct attr attr;
1827     struct param_list param[5];
1828     int secs;
1829    
1830     dbg(1,"enter\n");
1831     datawindow_mode(this_->roadbook_window, 1);
1832     if (nav)
1833     map=navigation_get_map(nav);
1834     if (map)
1835     mr=map_rect_new(map, NULL);
1836     //dbg(0,"nav=%p map=%p mr=%p\n", nav, map, mr);
1837     if (mr) {
1838     //dbg(0,"while loop\n");
1839     while ((item=map_rect_get_item(mr))) {
1840     //dbg(0,"item=%p\n", item);
1841     attr.u.str=NULL;
1842     if (item->type != type_nav_position) {
1843     item_attr_get(item, attr_navigation_long, &attr);
1844     if (attr.u.str == NULL) {
1845     continue;
1846     }
1847     dbg(2, "Command='%s'\n", attr.u.str);
1848     param[0].value=g_strdup(attr.u.str);
1849     } else
1850     param[0].value=_("Position");
1851     param[0].name=_("Command");
1852    
1853     item_attr_get(item, attr_length, &attr);
1854     dbg(2, "Length=%d\n", attr.u.num);
1855     param[1].name=_("Length");
1856    
1857     if ( attr.u.num >= 2000 )
1858     {
1859     param[1].value=g_strdup_printf("%5.1f %s",(float)attr.u.num / 1000, _("km") );
1860     }
1861     else
1862     {
1863     param[1].value=g_strdup_printf("%7d %s",attr.u.num, _("m"));
1864     }
1865    
1866     item_attr_get(item, attr_time, &attr);
1867     dbg(2, "Time=%d\n", attr.u.num);
1868     secs=attr.u.num/10;
1869     param[2].name=_("Time");
1870     if ( secs >= 3600 )
1871     {
1872     param[2].value=g_strdup_printf("%d:%02d:%02d",secs / 60, ( secs / 60 ) % 60 , secs % 60);
1873     }
1874     else
1875     {
1876     param[2].value=g_strdup_printf("%d:%02d",secs / 60, secs % 60);
1877     }
1878    
1879     item_attr_get(item, attr_destination_length, &attr);
1880     dbg(2, "Destlength=%d\n", attr.u.num);
1881     param[3].name=_("Destination Length");
1882     if ( attr.u.num >= 2000 )
1883     {
1884     param[3].value=g_strdup_printf("%5.1f %s",(float)attr.u.num / 1000, _("km") );
1885     }
1886     else
1887     {
1888     param[3].value=g_strdup_printf("%d %s",attr.u.num, _("m"));
1889     }
1890    
1891     item_attr_get(item, attr_destination_time, &attr);
1892     dbg(2, "Desttime=%d\n", attr.u.num);
1893     secs=attr.u.num/10;
1894     param[4].name=_("Destination Time");
1895     if ( secs >= 3600 )
1896     {
1897     param[4].value=g_strdup_printf("%d:%02d:%02d",secs / 3600, (secs / 60 ) % 60 , secs % 60);
1898     }
1899     else
1900     {
1901     param[4].value=g_strdup_printf("%d:%02d",secs / 60, secs % 60);
1902     }
1903     datawindow_add(this_->roadbook_window, param, 5);
1904     }
1905     map_rect_destroy(mr);
1906     }
1907     datawindow_mode(this_->roadbook_window, 0);
1908     }
1909    
1910     void
1911     navit_window_roadbook_destroy(struct navit *this_)
1912     {
1913     //dbg(0, "enter\n");
1914     navigation_unregister_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback);
1915     this_->roadbook_window=NULL;
1916     this_->roadbook_callback=NULL;
1917     }
1918     void
1919     navit_window_roadbook_new(struct navit *this_)
1920     {
1921     if (!this_->gui || this_->roadbook_callback || this_->roadbook_window) {
1922     return;
1923     }
1924    
1925     this_->roadbook_callback=callback_new_1(callback_cast(navit_window_roadbook_update), this_);
1926     navigation_register_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback);
1927     this_->roadbook_window=gui_datawindow_new(this_->gui, _("Roadbook"), NULL, callback_new_1(callback_cast(navit_window_roadbook_destroy), this_));
1928     navit_window_roadbook_update(this_);
1929     }
1930    
1931     void
1932     navit_remove_all_maps(struct navit *this_)
1933     {
1934     struct mapset *ms;
1935     struct map *map3;
1936    
1937     if (this_->mapsets)
1938     {
1939     struct mapset_handle *msh;
1940     ms=this_->mapsets->data;
1941     msh=mapset_open(ms);
1942     while (msh && (map3=mapset_next(msh, 0)))
1943     {
1944     struct attr map_name_attr;
1945     if (map_get_attr(map3,attr_name, &map_name_attr,NULL))
1946     {
1947     //dbg(0,"map name=%s",map_name_attr.u.str);
1948     if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
1949     {
1950     //dbg(0,"removing map\n");
1951     struct attr map_attr;
1952     map_attr.u.map=map3;
1953     map_attr.type=attr_map;
1954     mapset_remove_attr(ms, &map_attr);
1955     map_destroy(map3);
1956     }
1957     }
1958     }
1959     mapset_close(msh);
1960     }
1961     }
1962    
1963     void
1964     navit_add_all_maps(struct navit *this_)
1965     {
1966     struct mapset *ms;
1967     struct map *map3;
1968    
1969     if (this_->mapsets)
1970     {
1971     ms=this_->mapsets->data;
1972    
1973     struct attr type;
1974     struct attr parent;
1975     struct attr data;
1976     struct attr flags;
1977     struct map *map2;
1978     struct attr map2_attr;
1979     struct attr *attrs[4];
1980     char *map_file;
1981    
1982     parent.type=attr_navit;
1983     parent.u.navit=this_;
1984     type.type=attr_type;
1985     type.u.str="binfile";
1986     data.type=attr_data;
1987     map_file=g_strdup("/sdcard/zanavi/maps/borders.bin");
1988     data.u.str=map_file;
1989    
1990     //dbg(0,"map name=%s",map_file);
1991    
1992     flags.type=attr_flags;
1993     flags.u.num=0;
1994     attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
1995     map2=map_new(&parent, attrs);
1996     if (map2)
1997     {
1998     map2_attr.u.data=map2;
1999     map2_attr.type=attr_map;
2000     mapset_add_attr_name(ms, &map2_attr);
2001     }
2002     g_free(map_file);
2003    
2004     parent.type=attr_navit;
2005     parent.u.navit=this_;
2006     type.type=attr_type;
2007     type.u.str="binfile";
2008     data.type=attr_data;
2009     map_file=g_strdup("/sdcard/zanavi/maps/coastline.bin");
2010     data.u.str=map_file;
2011    
2012     //dbg(0,"map name=%s",map_file);
2013    
2014     flags.type=attr_flags;
2015     flags.u.num=0;
2016     attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
2017     map2=map_new(&parent, attrs);
2018     if (map2)
2019     {
2020     map2_attr.u.data=map2;
2021     map2_attr.type=attr_map;
2022     mapset_add_attr_name(ms, &map2_attr);
2023     }
2024     g_free(map_file);
2025    
2026     int i=1;
2027     for(i = 1; i < 10;i++)
2028     {
2029     struct map *map22;
2030     struct attr map22_attr;
2031     parent.type=attr_navit;
2032     parent.u.navit=this_;
2033     type.type=attr_type;
2034     type.u.str="binfile";
2035     data.type=attr_data;
2036     map_file=g_strdup_printf("/sdcard/zanavi/maps/navitmap_00%d.bin",i);
2037     data.u.str=map_file;
2038     //dbg(0,"map name=%s",map_file);
2039     flags.type=attr_flags;
2040     flags.u.num=0;
2041     attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
2042     map22=map_new(&parent, attrs);
2043     if (map22)
2044     {
2045     map22_attr.u.data=map22;
2046     map22_attr.type=attr_map;
2047     mapset_add_attr_name(ms, &map22_attr);
2048     }
2049     g_free(map_file);
2050     }
2051    
2052     i=10;
2053     for(i = 10; i < 21;i++)
2054     {
2055     parent.type=attr_navit;
2056     parent.u.navit=this_;
2057     type.type=attr_type;
2058     type.u.str="binfile";
2059     data.type=attr_data;
2060     map_file=g_strdup_printf("/sdcard/zanavi/maps/navitmap_0%d.bin",i);
2061     data.u.str=map_file;
2062     //dbg(0,"map name=%s",map_file);
2063     flags.type=attr_flags;
2064     flags.u.num=0;
2065     attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
2066     map2=map_new(&parent, attrs);
2067     if (map2)
2068     {
2069     map2_attr.u.data=map2;
2070     map2_attr.type=attr_map;
2071     mapset_add_attr_name(ms, &map2_attr);
2072     }
2073     g_free(map_file);
2074     }
2075     }
2076     }
2077    
2078     void
2079     navit_reload_maps(struct navit *this_)
2080     {
2081     navit_remove_all_maps(this_);
2082     navit_add_all_maps(this_);
2083     }
2084    
2085     void
2086     navit_init(struct navit *this_)
2087     {
2088     //dbg(0,"EEnter\n");
2089     struct mapset *ms;
2090     struct map *map;
2091     int callback;
2092     char *center_file;
2093    
2094     dbg(0,"enter gui %p graphics %p\n",this_->gui,this_->gra);
2095    
2096     if (!this_->gui && !(this_->flags & 2)) {
2097     dbg(0,"no gui\n");
2098     navit_destroy(this_);
2099     return;
2100     }
2101     if (!this_->gra && !(this_->flags & 1)) {
2102     dbg(0,"no graphics\n");
2103     navit_destroy(this_);
2104     return;
2105     }
2106     dbg(0,"Connecting gui to graphics\n");
2107     if (this_->gui && this_->gra && gui_set_graphics(this_->gui, this_->gra)) {
2108     struct attr attr_type_gui, attr_type_graphics;
2109     gui_get_attr(this_->gui, attr_type, &attr_type_gui, NULL);
2110     graphics_get_attr(this_->gra, attr_type, &attr_type_graphics, NULL);
2111     dbg(0,"failed to connect graphics '%s' to gui '%s'\n", attr_type_graphics.u.str, attr_type_gui.u.str);
2112     // dbg(0," Please see http://wiki.navit-project.org/index.php/Failed_to_connect_graphics_to_gui\n");
2113     // dbg(0," for explanations and solutions\n");
2114    
2115     navit_destroy(this_);
2116     return;
2117     }
2118     if (this_->speech && this_->navigation) {
2119     struct attr speech;
2120     speech.type=attr_speech;
2121     speech.u.speech=this_->speech;
2122     navigation_set_attr(this_->navigation, &speech);
2123     }
2124     dbg(0,"Initializing graphics\n");
2125     dbg(0,"Setting Vehicle\n");
2126     navit_set_vehicle(this_, this_->vehicle);
2127     dbg(0,"Adding dynamic maps to mapset %p\n",this_->mapsets);
2128     if (this_->mapsets) {
2129     struct mapset_handle *msh;
2130     ms=this_->mapsets->data;
2131     this_->progress_cb=callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_);
2132     msh=mapset_open(ms);
2133     while (msh && (map=mapset_next(msh, 0))) {
2134     //pass new callback instance for each map in the mapset to make map callback list destruction work correctly
2135     struct callback *pcb = callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_);
2136     map_add_callback(map, pcb);
2137     }
2138     mapset_close(msh);
2139    
2140     if (this_->route) {
2141     if ((map=route_get_map(this_->route))) {
2142     struct attr map_a,map_name;
2143     map_a.type=attr_map;
2144     map_a.u.map=map;
2145     map_name.type=attr_name;
2146     map_name.u.str="_ms_route";
2147     map_set_attr(map_a.u.map, &map_name);
2148     mapset_add_attr(ms, &map_a);
2149     }
2150     if ((map=route_get_graph_map(this_->route))) {
2151     struct attr map_a,active,map_name;
2152     map_a.type=attr_map;
2153     map_a.u.map=map;
2154     active.type=attr_active;
2155     active.u.num=0;
2156     map_name.type=attr_name;
2157     map_name.u.str="_ms_route_graph";
2158     map_set_attr(map_a.u.map, &map_name);
2159     mapset_add_attr(ms, &map_a);
2160     map_set_attr(map, &active);
2161     }
2162     route_set_mapset(this_->route, ms);
2163     route_set_projection(this_->route, transform_get_projection(this_->trans));
2164     }
2165     if (this_->tracking) {
2166     tracking_set_mapset(this_->tracking, ms);
2167     if (this_->route)
2168     tracking_set_route(this_->tracking, this_->route);
2169     }
2170     if (this_->navigation) {
2171     if ((map=navigation_get_map(this_->navigation))) {
2172     struct attr map_a,active,map_name;
2173     map_a.type=attr_map;
2174     map_a.u.map=map;
2175     active.type=attr_active;
2176     active.u.num=0;
2177     map_name.type=attr_name;
2178     map_name.u.str="_ms_navigation";
2179     map_set_attr(map_a.u.map, &map_name);
2180     mapset_add_attr(ms, &map_a);
2181     map_set_attr(map, &active);
2182     }
2183     }
2184     if (this_->tracking) {
2185     if ((map=tracking_get_map(this_->tracking))) {
2186 zoff99 14 struct attr map_a,active,map_name;
2187 zoff99 2 map_a.type=attr_map;
2188     map_a.u.map=map;
2189     active.type=attr_active;
2190     active.u.num=0;
2191 zoff99 14 map_name.type=attr_name;
2192     map_name.u.str="_ms_tracking";
2193     map_set_attr(map_a.u.map, &map_name);
2194 zoff99 2 mapset_add_attr(ms, &map_a);
2195     map_set_attr(map, &active);
2196     }
2197     }
2198 zoff99 14 // *DISABLED* navit_add_former_destinations_from_file(this_);
2199 zoff99 2 }
2200     if (this_->route) {
2201     struct attr callback;
2202     this_->route_cb=callback_new_attr_1(callback_cast(navit_redraw_route), attr_route_status, this_);
2203     callback.type=attr_callback;
2204     callback.u.callback=this_->route_cb;
2205     route_add_attr(this_->route, &callback);
2206     }
2207     if (this_->navigation) {
2208     if (this_->speech) {
2209     this_->nav_speech_cb=callback_new_1(callback_cast(navit_speak), this_);
2210     navigation_register_callback(this_->navigation, attr_navigation_speech, this_->nav_speech_cb);
2211     }
2212     if (this_->route)
2213     navigation_set_route(this_->navigation, this_->route);
2214     }
2215     dbg(0,"Setting Center\n");
2216     center_file = bookmarks_get_center_file(FALSE);
2217     bookmarks_set_center_from_file(this_->bookmarks, center_file);
2218     g_free(center_file);
2219     #if 0
2220     if (this_->menubar) {
2221     men=menu_add(this_->menubar, "Data", menu_type_submenu, NULL);
2222     if (men) {
2223     navit_add_menu_windows_items(this_, men);
2224     }
2225     }
2226     #endif
2227     global_navit=this_;
2228     #if 0
2229     navit_window_roadbook_new(this_);
2230     navit_window_items_new(this_);
2231     #endif
2232    
2233     messagelist_init(this_->messages);
2234    
2235     navit_set_cursors(this_);
2236    
2237     callback_list_call_attr_1(this_->attr_cbl, attr_navit, this_);
2238     callback=(this_->ready == 2);
2239     dbg(0,"pre this_->ready=%d\n",this_->ready);
2240     this_->ready|=1;
2241     dbg(0,"set this_->ready=%d\n",this_->ready);
2242     //dbg(0,"ready=%d\n",this_->ready);
2243     if (this_->ready == 3)
2244     {
2245     //dbg(0,"navit_draw_async_003\n");
2246     navit_draw_async(this_, 1);
2247     }
2248     if (callback)
2249     callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_);
2250     #if 0
2251     routech_test(this_);
2252     #endif
2253     //dbg(0,"1111111111\n");
2254     }
2255    
2256     void
2257     navit_zoom_to_rect(struct navit *this_, struct coord_rect *r)
2258     {
2259     //dbg(0,"EEnter\n");
2260     struct coord c;
2261     int scale=16;
2262    
2263     c.x=(r->rl.x+r->lu.x)/2;
2264     c.y=(r->rl.y+r->lu.y)/2;
2265     transform_set_center(this_->trans, &c);
2266     dbg(1,"%x,%x-%x,%x\n", r->rl.x,r->rl.y,r->lu.x,r->lu.y);
2267     while (scale < 1<<20) {
2268     struct point p1,p2;
2269     transform_set_scale(this_->trans, scale);
2270     transform_setup_source_rect(this_->trans);
2271     transform(this_->trans, transform_get_projection(this_->trans), &r->lu, &p1, 1, 0, 0, NULL);
2272     transform(this_->trans, transform_get_projection(this_->trans), &r->rl, &p2, 1, 0, 0, NULL);
2273     dbg(1,"%d,%d-%d,%d\n",p1.x,p1.y,p2.x,p2.y);
2274     if (p1.x < 0 || p2.x < 0 || p1.x > this_->w || p2.x > this_->w ||
2275     p1.y < 0 || p2.y < 0 || p1.y > this_->h || p2.y > this_->h)
2276     scale*=2;
2277     else
2278     break;
2279    
2280     }
2281     if (this_->ready == 3)
2282     {
2283     //dbg(0,"navit_draw_async_004\n");
2284     navit_draw_async(this_,0);
2285     }
2286     }
2287    
2288     void
2289     navit_zoom_to_route(struct navit *this_, int orientation)
2290     {
2291     //dbg(0,"EEnter\n");
2292     struct map *map;
2293     struct map_rect *mr=NULL;
2294     struct item *item;
2295     struct coord c;
2296     struct coord_rect r;
2297     int count=0;
2298     if (! this_->route)
2299     return;
2300     dbg(1,"enter\n");
2301     map=route_get_map(this_->route);
2302     dbg(1,"map=%p\n",map);
2303     if (map)
2304     mr=map_rect_new(map, NULL);
2305     dbg(1,"mr=%p\n",mr);
2306     if (mr) {
2307     while ((item=map_rect_get_item(mr))) {
2308     dbg(1,"item=%s\n", item_to_name(item->type));
2309     while (item_coord_get(item, &c, 1)) {
2310     dbg(1,"coord\n");
2311     if (!count)
2312     r.lu=r.rl=c;
2313     else
2314     coord_rect_extend(&r, &c);
2315     count++;
2316     }
2317     }
2318     map_rect_destroy(mr);
2319     }
2320     if (! count)
2321     return;
2322     if (orientation != -1)
2323     transform_set_yaw(this_->trans, orientation);
2324     navit_zoom_to_rect(this_, &r);
2325     }
2326    
2327     static void
2328     navit_cmd_zoom_to_route(struct navit *this)
2329     {
2330     //dbg(0,"EEnter\n");
2331     navit_zoom_to_route(this, 0);
2332     }
2333    
2334    
2335     /**
2336     * show point on map
2337     *
2338     * @param navit The navit instance
2339     * @param center The point where to center the map, including its projection
2340     * @returns nothing
2341     */
2342     void
2343     navit_set_center(struct navit *this_, struct pcoord *center, int set_timeout)
2344     {
2345     //dbg(0,"EEnter\n");
2346     struct coord *c=transform_center(this_->trans);
2347     struct coord c1,c2;
2348     enum projection pro = transform_get_projection(this_->trans);
2349     if (pro != center->pro) {
2350     c1.x = center->x;
2351     c1.y = center->y;
2352     transform_from_to(&c1, center->pro, &c2, pro);
2353     } else {
2354     c2.x = center->x;
2355     c2.y = center->y;
2356     }
2357     *c=c2;
2358     if (set_timeout)
2359     navit_set_timeout(this_);
2360     if (this_->ready == 3)
2361     navit_draw(this_);
2362     }
2363    
2364     static void
2365     navit_set_center_coord_screen(struct navit *this_, struct coord *c, struct point *p, int set_timeout)
2366     {
2367     //dbg(0,"EEnter\n");
2368     int width, height;
2369     struct point po;
2370     transform_set_center(this_->trans, c);
2371     transform_get_size(this_->trans, &width, &height);
2372     po.x=width/2;
2373     po.y=height/2;
2374     update_transformation(this_->trans, &po, p, NULL);
2375     if (set_timeout)
2376     navit_set_timeout(this_);
2377     }
2378    
2379     /**
2380     * Links all vehicles to a cursor depending on the current profile.
2381     *
2382     * @param this_ A navit instance
2383     * @author Ralph Sennhauser (10/2009)
2384     */
2385     static void
2386     navit_set_cursors(struct navit *this_)
2387     {
2388     //dbg(0,"EEnter\n");
2389     struct attr name;
2390     struct navit_vehicle *nv;
2391     struct cursor *c;
2392     GList *v;
2393    
2394     v=g_list_first(this_->vehicles); // GList of navit_vehicles
2395     while (v) {
2396     nv=v->data;
2397     if (vehicle_get_attr(nv->vehicle, attr_cursorname, &name, NULL)) {
2398     if (!strcmp(name.u.str,"none"))
2399     c=NULL;
2400     else
2401     c=layout_get_cursor(this_->layout_current, name.u.str);
2402     } else
2403     c=layout_get_cursor(this_->layout_current, "default");
2404     vehicle_set_cursor(nv->vehicle, c, 0);
2405     v=g_list_next(v);
2406     }
2407     return;
2408     }
2409    
2410     static int
2411     navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir)
2412     {
2413     //dbg(0,"EEnter\n");
2414     int width, height;
2415     struct navit_vehicle *nv=this_->vehicle;
2416    
2417     float offset=this_->radius; // Cursor offset from the center of the screen (percent).
2418     #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 */
2419     float min_offset = 0.; // Percent offset at min_offset_speed.
2420     float max_offset = 30.; // Percent offset at max_offset_speed.
2421     int min_offset_speed = 2; // Speed in km/h
2422     int max_offset_speed = 50; // Speed ini km/h
2423     // Calculate cursor offset from the center of the screen, upon speed.
2424     if (nv->speed <= min_offset_speed) {
2425     offset = min_offset;
2426     } else if (nv->speed > max_offset_speed) {
2427     offset = max_offset;
2428     } else {
2429     offset = (max_offset - min_offset) / (max_offset_speed - min_offset_speed) * (nv->speed - min_offset_speed);
2430     }
2431     #endif
2432    
2433     transform_get_size(this_->trans, &width, &height);
2434     if (this_->orientation == -1 || keep_orientation) {
2435     p->x=50*width/100;
2436     p->y=(50 + offset)*height/100;
2437     if (dir)
2438     *dir=keep_orientation?this_->orientation:nv->dir;
2439     } else {
2440     int mdir;
2441     if (this_->tracking && this_->tracking_flag) {
2442     mdir = tracking_get_angle(this_->tracking) - this_->orientation;
2443     } else {
2444     mdir=nv->dir-this_->orientation;
2445     }
2446    
2447     p->x=(50 - offset*sin(M_PI*mdir/180.))*width/100;
2448     p->y=(50 + offset*cos(M_PI*mdir/180.))*height/100;
2449     if (dir)
2450     *dir=this_->orientation;
2451     }
2452     return 1;
2453     }
2454    
2455     void
2456     navit_set_center_cursor(struct navit *this_, int autozoom, int keep_orientation)
2457     {
2458     //dbg(0,"EEnter\n");
2459     int dir;
2460     struct point pn;
2461     struct navit_vehicle *nv=this_->vehicle;
2462     navit_get_cursor_pnt(this_, &pn, keep_orientation, &dir);
2463     transform_set_yaw(this_->trans, dir);
2464     navit_set_center_coord_screen(this_, &nv->coord, &pn, 0);
2465     if (autozoom)
2466     navit_autozoom(this_, &nv->coord, nv->speed, 0);
2467     }
2468    
2469     static void
2470     navit_set_center_cursor_draw(struct navit *this_)
2471     {
2472     //dbg(0,"EEnter\n");
2473     navit_set_center_cursor(this_,1,0);
2474     if (this_->ready == 3)
2475     {
2476     //dbg(0,"navit_draw_async_005\n");
2477     navit_draw_async(this_, 1);
2478     }
2479     }
2480    
2481     static void
2482     navit_cmd_set_center_cursor(struct navit *this_)
2483     {
2484     //dbg(0,"EEnter\n");
2485     navit_set_center_cursor_draw(this_);
2486     }
2487    
2488     void
2489     navit_set_center_screen(struct navit *this_, struct point *p, int set_timeout)
2490     {
2491     //dbg(0,"EEnter\n");
2492     struct coord c;
2493     struct pcoord pc;
2494     transform_reverse(this_->trans, p, &c);
2495     pc.x = c.x;
2496     pc.y = c.y;
2497     pc.pro = transform_get_projection(this_->trans);
2498     navit_set_center(this_, &pc, set_timeout);
2499     }
2500    
2501     #if 0
2502     switch((*attrs)->type) {
2503     case attr_zoom:
2504     zoom=(*attrs)->u.num;
2505     break;
2506     case attr_center:
2507     g=*((*attrs)->u.coord_geo);
2508     break;
2509     #endif
2510    
2511     static int
2512     navit_set_attr_do(struct navit *this_, struct attr *attr, int init)
2513     {
2514     //dbg(0,"EEnter\n");
2515     int dir=0, orient_old=0, attr_updated=0;
2516     struct coord co;
2517     long zoom;
2518     GList *l;
2519     struct navit_vehicle *nv;
2520     struct layout *lay;
2521     struct attr active;
2522     active.type=attr_active;
2523     active.u.num=0;
2524    
2525     switch (attr->type) {
2526     case attr_autozoom:
2527     attr_updated=(this_->autozoom_secs != attr->u.num);
2528     this_->autozoom_secs = attr->u.num;
2529     break;
2530     case attr_autozoom_active:
2531     attr_updated=(this_->autozoom_active != attr->u.num);
2532     this_->autozoom_active = attr->u.num;
2533     break;
2534     case attr_center:
2535     transform_from_geo(transform_get_projection(this_->trans), attr->u.coord_geo, &co);
2536     dbg(1,"0x%x,0x%x\n",co.x,co.y);
2537     transform_set_center(this_->trans, &co);
2538     break;
2539     case attr_drag_bitmap:
2540     attr_updated=(this_->drag_bitmap != !!attr->u.num);
2541     this_->drag_bitmap=!!attr->u.num;
2542     break;
2543     case attr_flags:
2544     attr_updated=(this_->flags != attr->u.num);
2545     this_->flags=attr->u.num;
2546     break;
2547     case attr_flags_graphics:
2548     attr_updated=(this_->graphics_flags != attr->u.num);
2549     this_->graphics_flags=attr->u.num;
2550     break;
2551     case attr_follow:
2552     if (!this_->vehicle)
2553     return 0;
2554     attr_updated=(this_->vehicle->follow_curr != attr->u.num);
2555     this_->vehicle->follow_curr = attr->u.num;
2556     break;
2557     case attr_layout:
2558     if(this_->layout_current!=attr->u.layout) {
2559     this_->layout_current=attr->u.layout;
2560     graphics_font_destroy_all(this_->gra);
2561     navit_set_cursors(this_);
2562     if (this_->ready == 3)
2563     navit_draw(this_);
2564     attr_updated=1;
2565     }
2566     break;
2567     case attr_layout_name:
2568     l=this_->layouts;
2569     while (l) {
2570     lay=l->data;
2571     if (!strcmp(lay->name,attr->u.str)) {
2572     struct attr attr;
2573     attr.type=attr_layout;
2574     attr.u.layout=lay;
2575     return navit_set_attr_do(this_, &attr, init);
2576     }
2577     l=g_list_next(l);
2578     }
2579     return 0;
2580     case attr_map_border:
2581     if (this_->border != attr->u.num) {
2582     this_->border=attr->u.num;
2583     attr_updated=1;
2584     }
2585     break;
2586     case attr_orientation:
2587     orient_old=this_->orientation;
2588     this_->orientation=attr->u.num;
2589     if (!init) {
2590     if (this_->orientation != -1) {
2591     dir = this_->orientation;
2592     } else {
2593     if (this_->vehicle) {
2594     dir = this_->vehicle->dir;
2595     }
2596     }
2597     transform_set_yaw(this_->trans, dir);
2598     if (orient_old != this_->orientation) {
2599     #if 0
2600     if (this_->ready == 3)
2601     navit_draw(this_);
2602     #endif
2603     attr_updated=1;
2604     }
2605     }
2606     break;
2607     case attr_osd_configuration:
2608     dbg(0,"setting osd_configuration to %d (was %d)\n", attr->u.num, this_->osd_configuration);
2609     attr_updated=(this_->osd_configuration != attr->u.num);
2610     this_->osd_configuration=attr->u.num;
2611     break;
2612     case attr_pitch:
2613     attr_updated=(this_->pitch != attr->u.num);
2614     this_->pitch=attr->u.num;
2615     transform_set_pitch(this_->trans, this_->pitch);
2616     if (!init && attr_updated && this_->ready == 3)
2617     navit_draw(this_);
2618     break;
2619     case attr_projection:
2620     if(this_->trans && transform_get_projection(this_->trans) != attr->u.projection) {
2621     navit_projection_set(this_, attr->u.projection, !init);
2622     attr_updated=1;
2623     }
2624     break;
2625     case attr_radius:
2626     attr_updated=(this_->radius != attr->u.num);
2627     this_->radius=attr->u.num;
2628     break;
2629     case attr_recent_dest:
2630     attr_updated=(this_->recentdest_count != attr->u.num);
2631     this_->recentdest_count=attr->u.num;
2632     break;
2633     case attr_speech:
2634     if(this_->speech && this_->speech != attr->u.speech) {
2635     attr_updated=1;
2636     this_->speech = attr->u.speech;
2637     }
2638     break;
2639     case attr_timeout:
2640     attr_updated=(this_->center_timeout != attr->u.num);
2641     this_->center_timeout = attr->u.num;
2642     break;
2643     case attr_tracking:
2644     attr_updated=(this_->tracking_flag != !!attr->u.num);
2645     this_->tracking_flag=!!attr->u.num;
2646     break;
2647     case attr_transformation:
2648     this_->trans=attr->u.transformation;
2649     break;
2650     case attr_use_mousewheel:
2651     attr_updated=(this_->use_mousewheel != !!attr->u.num);
2652     this_->use_mousewheel=!!attr->u.num;
2653     break;
2654     case attr_vehicle:
2655     l=this_->vehicles;
2656     while(l) {
2657     nv=l->data;
2658     if (nv->vehicle == attr->u.vehicle) {
2659     if (!this_->vehicle || this_->vehicle->vehicle != attr->u.vehicle) {
2660     if (this_->vehicle)
2661     vehicle_set_attr(this_->vehicle->vehicle, &active);
2662     active.u.num=1;
2663     vehicle_set_attr(nv->vehicle, &active);
2664     attr_updated=1;
2665     }
2666     navit_set_vehicle(this_, nv);
2667     }
2668     l=g_list_next(l);
2669     }
2670     break;
2671     case attr_zoom:
2672     zoom=transform_get_scale(this_->trans);
2673     attr_updated=(zoom != attr->u.num);
2674     transform_set_scale(this_->trans, attr->u.num);
2675     if (attr_updated && !init)
2676     navit_draw(this_);
2677     break;
2678     case attr_zoom_min:
2679     attr_updated=(attr->u.num != this_->zoom_min);
2680     this_->zoom_min=attr->u.num;
2681     break;
2682     case attr_zoom_max:
2683     attr_updated=(attr->u.num != this_->zoom_max);
2684     this_->zoom_max=attr->u.num;
2685     break;
2686     case attr_message:
2687     navit_add_message(this_, attr->u.str);
2688     break;
2689     case attr_follow_cursor:
2690     attr_updated=(this_->follow_cursor != !!attr->u.num);
2691     this_->follow_cursor=!!attr->u.num;
2692     break;
2693     case attr_imperial:
2694     attr_updated=(this_->imperial != attr->u.num);
2695     this_->imperial=attr->u.num;
2696     break;
2697     default:
2698     return 0;
2699     }
2700     if (attr_updated && !init) {
2701     callback_list_call_attr_2(this_->attr_cbl, attr->type, this_, attr);
2702     if (attr->type == attr_osd_configuration)
2703     graphics_draw_mode(this_->gra, draw_mode_end);
2704     }
2705     return 1;
2706     }
2707    
2708     int
2709     navit_set_attr(struct navit *this_, struct attr *attr)
2710     {
2711     //dbg(0,"EEnter\n");
2712     return navit_set_attr_do(this_, attr, 0);
2713     }
2714    
2715     int
2716     navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
2717     {
2718     //dbg(0,"EEnter\n");
2719     struct message *msg;
2720     int len,offset;
2721     int ret=1;
2722    
2723     switch (type) {
2724     case attr_message:
2725     msg = navit_get_messages(this_);
2726    
2727     if (!msg) {
2728     return 0;
2729     }
2730    
2731     len = 0;
2732     while (msg) {
2733     len += strlen(msg->text) + 1;
2734     msg = msg->next;
2735     }
2736     attr->u.str = g_malloc(len + 1);
2737    
2738     msg = navit_get_messages(this_);
2739     offset = 0;
2740     while (msg) {
2741     g_stpcpy((attr->u.str + offset), msg->text);
2742     offset += strlen(msg->text);
2743     attr->u.str[offset] = '\n';
2744     offset++;
2745    
2746     msg = msg->next;
2747     }
2748    
2749     attr->u.str[len] = '\0';
2750     break;
2751     case attr_imperial:
2752     attr->u.num=this_->imperial;
2753     break;
2754     case attr_bookmark_map:
2755     attr->u.map=bookmarks_get_map(this_->bookmarks);
2756     break;
2757     case attr_bookmarks:
2758     attr->u.bookmarks=this_->bookmarks;
2759     break;
2760     case attr_callback_list:
2761     attr->u.callback_list=this_->attr_cbl;
2762     break;
2763     case attr_destination:
2764     if (! this_->destination_valid)
2765     return 0;
2766     attr->u.pcoord=&this_->destination;
2767     break;
2768     case attr_displaylist:
2769     attr->u.displaylist=this_->displaylist;
2770     return (attr->u.displaylist != NULL);
2771     case attr_follow:
2772     if (!this_->vehicle)
2773     return 0;
2774     attr->u.num=this_->vehicle->follow_curr;
2775     break;
2776     case attr_former_destination_map:
2777     attr->u.map=this_->former_destination;
2778     break;
2779     case attr_graphics:
2780     attr->u.graphics=this_->gra;
2781     ret=(attr->u.graphics != NULL);
2782     break;
2783     case attr_gui:
2784     attr->u.gui=this_->gui;
2785     ret=(attr->u.gui != NULL);
2786     break;
2787     case attr_layout:
2788     if (iter)
2789     {
2790     if (iter->u.list)
2791     {
2792     iter->u.list=g_list_next(iter->u.list);
2793     }
2794     else
2795     {
2796     iter->u.list=this_->layouts;
2797     }
2798     if (!iter->u.list)
2799     {
2800     return 0;
2801     }
2802     attr->u.layout=(struct layout *)iter->u.list->data;
2803     }
2804     else
2805     {
2806     attr->u.layout=this_->layout_current;
2807     }
2808     break;
2809     case attr_map:
2810     if (iter && this_->mapsets) {
2811     if (!iter->u.mapset_handle) {
2812     iter->u.mapset_handle=mapset_open((struct mapset *)this_->mapsets->data);
2813     }
2814     attr->u.map=mapset_next(iter->u.mapset_handle, 0);
2815     if(!attr->u.map) {
2816     mapset_close(iter->u.mapset_handle);
2817     return 0;
2818     }
2819     } else {
2820     return 0;
2821     }
2822     break;
2823     case attr_mapset:
2824     attr->u.mapset=this_->mapsets->data;
2825     ret=(attr->u.mapset != NULL);
2826     break;
2827     case attr_navigation:
2828     attr->u.navigation=this_->navigation;
2829     break;
2830     case attr_orientation:
2831     attr->u.num=this_->orientation;
2832     break;
2833     case attr_osd_configuration:
2834     attr->u.num=this_->osd_configuration;
2835     break;
2836     case attr_pitch:
2837     attr->u.num=transform_get_pitch(this_->trans);
2838     break;
2839     case attr_projection:
2840     if(this_->trans) {
2841     attr->u.num=transform_get_projection(this_->trans);
2842     } else {
2843     return 0;
2844     }
2845     break;
2846     case attr_route:
2847     attr->u.route=this_->route;
2848     break;
2849     case attr_speech:
2850     attr->u.speech=this_->speech;
2851     break;
2852     case attr_tracking:
2853     attr->u.num=this_->tracking_flag;
2854     break;
2855     case attr_trackingo:
2856     attr->u.tracking=this_->tracking;
2857     break;
2858     case attr_transformation:
2859     attr->u.transformation=this_->trans;
2860     break;
2861     case attr_vehicle:
2862     if(iter) {
2863     if(iter->u.list) {
2864     iter->u.list=g_list_next(iter->u.list);
2865     } else {
2866     iter->u.list=this_->vehicles;
2867     }
2868     if(!iter->u.list)
2869     return 0;
2870     attr->u.vehicle=((struct navit_vehicle*)iter->u.list->data)->vehicle;
2871     } else {
2872     if(this_->vehicle) {
2873     attr->u.vehicle=this_->vehicle->vehicle;
2874     } else {
2875     return 0;
2876     }
2877     }
2878     break;
2879     case attr_vehicleprofile:
2880     attr->u.vehicleprofile=this_->vehicleprofile;
2881     break;
2882     case attr_zoom:
2883     attr->u.num=transform_get_scale(this_->trans);
2884     break;
2885     case attr_autozoom_active:
2886     attr->u.num=this_->autozoom_active;
2887     break;
2888     case attr_follow_cursor:
2889     attr->u.num=this_->follow_cursor;
2890     break;
2891     default:
2892     return 0;
2893     }
2894     attr->type=type;
2895     return ret;
2896     }
2897    
2898     static int
2899     navit_add_log(struct navit *this_, struct log *log)
2900     {
2901     struct attr type_attr;
2902     if (!log_get_attr(log, attr_type, &type_attr, NULL))
2903     return 0;
2904     if (!strcmp(type_attr.u.str, "textfile_debug")) {
2905     char *header = "type=track_tracked\n";
2906     if (this_->textfile_debug_log)
2907     return 0;
2908     log_set_header(log, header, strlen(header));
2909     this_->textfile_debug_log=log;
2910     return 1;
2911     }
2912     return 0;
2913     }
2914    
2915     static int
2916     navit_add_layout(struct navit *this_, struct layout *layout)
2917     {
2918     //dbg(0,"EEnter\n");
2919     struct attr active;
2920     this_->layouts = g_list_append(this_->layouts, layout);
2921     layout_get_attr(layout, attr_active, &active, NULL);
2922     if(active.u.num || !this_->layout_current) {
2923     this_->layout_current=layout;
2924     return 1;
2925     }
2926     return 0;
2927     }
2928    
2929     int
2930     navit_add_attr(struct navit *this_, struct attr *attr)
2931     {
2932     //dbg(0,"EEnter\n");
2933    
2934     int ret=1;
2935     switch (attr->type) {
2936     case attr_callback:
2937     navit_add_callback(this_, attr->u.callback);
2938     break;
2939     case attr_log:
2940     ret=navit_add_log(this_, attr->u.log);
2941     break;
2942     case attr_gui:
2943     ret=navit_set_gui(this_, attr->u.gui);
2944     break;
2945     case attr_graphics:
2946     ret=navit_set_graphics(this_, attr->u.graphics);
2947     break;
2948     case attr_layout:
2949     ret=navit_add_layout(this_, attr->u.layout);
2950     break;
2951     case attr_route:
2952     this_->route=attr->u.route;
2953     break;
2954     case attr_mapset:
2955     this_->mapsets = g_list_append(this_->mapsets, attr->u.mapset);
2956     break;
2957     case attr_navigation:
2958     this_->navigation=attr->u.navigation;
2959     break;
2960     case attr_recent_dest:
2961     this_->recentdest_count = attr->u.num;
2962     break;
2963     case attr_speech:
2964     this_->speech=attr->u.speech;
2965     break;
2966     case attr_tracking:
2967     this_->tracking=attr->u.tracking;
2968     break;
2969     case attr_vehicle:
2970     ret=navit_add_vehicle(this_, attr->u.vehicle);
2971     break;
2972     case attr_vehicleprofile:
2973     this_->vehicleprofiles=g_list_prepend(this_->vehicleprofiles, attr->u.vehicleprofile);
2974     break;
2975     case attr_autozoom_min:
2976     this_->autozoom_min = attr->u.num;
2977     break;
2978     default:
2979     return 0;
2980     }
2981     callback_list_call_attr_2(this_->attr_cbl, attr->type, this_, attr);
2982     return ret;
2983     }
2984    
2985     int
2986     navit_remove_attr(struct navit *this_, struct attr *attr)
2987     {
2988     int ret=1;
2989     switch (attr->type) {
2990     case attr_callback:
2991     navit_remove_callback(this_, attr->u.callback);
2992     break;
2993     default:
2994     return 0;
2995     }
2996     return ret;
2997     }
2998    
2999     struct attr_iter *
3000     navit_attr_iter_new(void)
3001     {
3002     return g_new0(struct attr_iter, 1);
3003     }
3004    
3005     void
3006     navit_attr_iter_destroy(struct attr_iter *iter)
3007     {
3008     g_free(iter);
3009     }
3010    
3011     void
3012     navit_add_callback(struct navit *this_, struct callback *cb)
3013     {
3014     //dbg(0,"EEnter\n");
3015    
3016     callback_list_add(this_->attr_cbl, cb);
3017     }
3018    
3019     void
3020     navit_remove_callback(struct navit *this_, struct callback *cb)
3021     {
3022     //dbg(0,"EEnter\n");
3023    
3024     callback_list_remove(this_->attr_cbl, cb);
3025     }
3026    
3027     /**
3028     * Toggle the cursor update : refresh the map each time the cursor has moved (instead of only when it reaches a border)
3029     *
3030     * @param navit The navit instance
3031     * @returns nothing
3032     */
3033    
3034     static void
3035     navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt)
3036     {
3037     //dbg(0,"EEnter\n");
3038    
3039     struct point cursor_pnt;
3040     enum projection pro;
3041    
3042     if (this_->blocked)
3043     return;
3044     if (pnt)
3045     {
3046     cursor_pnt=*pnt;
3047     }
3048     else
3049     {
3050     pro=transform_get_projection(this_->trans_cursor);
3051     if (!pro)
3052     return;
3053     transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
3054     }
3055     //dbg(0,"xx=%d\n",cursor_pnt.x);
3056     //dbg(0,"yy=%d\n",cursor_pnt.y);
3057    
3058     global_vehicle_pos_onscreen.x=cursor_pnt.x;
3059     global_vehicle_pos_onscreen.y=cursor_pnt.y;
3060    
3061    
3062     //dbg(0,"xx=%d\n",pnt->x);
3063     //dbg(0,"yy=%d\n",pnt->y);
3064     //dbg(0,"vehicle_draw_001\n");
3065     vehicle_draw(nv->vehicle, this_->gra, &cursor_pnt, pnt ? 0:1, nv->dir-transform_get_yaw(this_->trans_cursor), nv->speed);
3066     #if 0
3067     if (pnt)
3068     pnt2=*pnt;
3069     else {
3070     pro=transform_get_projection(this_->trans);
3071     transform(this_->trans, pro, &nv->coord, &pnt2, 1);
3072     }
3073     #if 1
3074     cursor_draw(nv->cursor, &pnt2, nv->dir-transform_get_angle(this_->trans, 0), nv->speed > 2, pnt == NULL);
3075     #else
3076     cursor_draw(nv->cursor, &pnt2, nv->dir-transform_get_angle(this_->trans, 0), nv->speed > 2, 1);
3077     #endif
3078     #endif
3079     }
3080    
3081     static void
3082     navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
3083     {
3084     // dbg(0,"EEnter\n");
3085    
3086     struct attr attr_valid, attr_dir, attr_speed, attr_pos;
3087     struct pcoord cursor_pc;
3088     struct point cursor_pnt, *pnt=&cursor_pnt;
3089     struct tracking *tracking=NULL;
3090     struct pcoord pc[16];
3091     enum projection pro=transform_get_projection(this_->trans_cursor);
3092     int count;
3093     int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *);
3094     void *attr_object;
3095     char *destination_file;
3096    
3097     // dbg(0,"navit_vehicle_update_001 %d\n",pro);
3098     //profile(0,NULL);
3099     if (this_->ready != 3) {
3100     //profile(0,"return 1\n");
3101     return;
3102     }
3103     navit_layout_switch(this_);
3104     if (this_->vehicle == nv && this_->tracking_flag)
3105     tracking=this_->tracking;
3106     if (tracking) {
3107     tracking_update(tracking, nv->vehicle, this_->vehicleprofile, pro);
3108     attr_object=tracking;
3109     get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))tracking_get_attr;
3110     } else {
3111     attr_object=nv->vehicle;
3112     get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))vehicle_get_attr;
3113     }
3114     if (get_attr(attr_object, attr_position_valid, &attr_valid, NULL))
3115     if (!attr_valid.u.num != attr_position_valid_invalid)
3116     return;
3117     if (! get_attr(attr_object, attr_position_direction, &attr_dir, NULL) ||
3118     ! get_attr(attr_object, attr_position_speed, &attr_speed, NULL) ||
3119     ! get_attr(attr_object, attr_position_coord_geo, &attr_pos, NULL)) {
3120     // profile(0,"return 2\n");
3121     return;
3122     }
3123     nv->dir=*attr_dir.u.numd;
3124     nv->speed=*attr_speed.u.numd;
3125     transform_from_geo(pro, attr_pos.u.coord_geo, &nv->coord);
3126     if (nv != this_->vehicle)
3127     {
3128     //dbg(0,"---> 2 x=%d\n", nv->coord.x);
3129     //dbg(0,"---> 2 y=%d\n", nv->coord.y);
3130     // dbg(0,"vehicle_draw_002\n");
3131     navit_vehicle_draw(this_, nv, NULL);
3132     // profile(0,"return 3\n");
3133     return;
3134     }
3135     cursor_pc.x = nv->coord.x;
3136     cursor_pc.y = nv->coord.y;
3137     cursor_pc.pro = pro;
3138     if (this_->route) {
3139     if (tracking)
3140     route_set_position_from_tracking(this_->route, tracking, pro);
3141     else
3142     route_set_position(this_->route, &cursor_pc);
3143     }
3144     callback_list_call_attr_0(this_->attr_cbl, attr_position);
3145     navit_textfile_debug_log(this_, "type=trackpoint_tracked");
3146     if (this_->gui && nv->speed > MYSTERY_SPEED)
3147     navit_disable_suspend();
3148     transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL);
3149     if (this_->button_pressed != 1 && this_->follow_cursor && nv->follow_curr <= nv->follow &&
3150     (nv->follow_curr == 1 || !transform_within_border(this_->trans_cursor, &cursor_pnt, this_->border)))
3151     {
3152     navit_set_center_cursor_draw(this_);
3153     //dbg(0,"---> xxCENTER\n");
3154     //dbg(0,"---> 3 x=%d\n", nv->coord.x);
3155     //dbg(0,"---> 3 y=%d\n", nv->coord.y);
3156    
3157     //dbg(0,"---> 4 x=%d\n", cursor_pnt.x);
3158     //dbg(0,"---> 4 y=%d\n", cursor_pnt.y);
3159    
3160     //global_vehicle_pos_onscreen.x=cursor_pnt.x;
3161     //global_vehicle_pos_onscreen.y=cursor_pnt.y;
3162    
3163     }
3164     else
3165     {
3166     //dbg(0,"vehicle_draw_003\n");
3167     navit_vehicle_draw(this_, nv, pnt);
3168     //global_vehicle_pos_onscreen.x=pnt->x;
3169     //global_vehicle_pos_onscreen.y=pnt->y;
3170     //dbg(0,"---> x=%d\n", pnt->x);
3171     //dbg(0,"---> y=%d\n", pnt->y);
3172     }
3173    
3174     if (nv->follow_curr > 1)
3175     nv->follow_curr--;
3176     else
3177     nv->follow_curr=nv->follow;
3178     callback_list_call_attr_2(this_->attr_cbl, attr_position_coord_geo, this_, nv->vehicle);
3179    
3180     /* Finally, if we reached our destination, stop navigation. */
3181     if (this_->route) {
3182     switch(route_destination_reached(this_->route)) {
3183     case 1:
3184     route_remove_waypoint(this_->route);
3185     count=route_get_destinations(this_->route, pc, 16);
3186     destination_file = bookmarks_get_destination_file(TRUE);
3187     bookmarks_append_coord(this_->bookmarks, destination_file, pc, count, "former_itinerary_part", NULL, NULL, this_->recentdest_count);
3188 zoff99 14 #ifdef HAVE_API_ANDROID
3189     // waypoint reached
3190     android_return_generic_int(5, 1);
3191     #endif
3192 zoff99 2 break;
3193     case 2:
3194     navit_set_destination(this_, NULL, NULL, 0);
3195 zoff99 14 // ** inform java that we reached our destination **
3196     #ifdef HAVE_API_ANDROID
3197     android_return_generic_int(4, 1);
3198     #endif
3199 zoff99 2 break;
3200     }
3201     }
3202     //profile(0,"return 5\n");
3203     // dbg(0,"navit_vehicle_update_999\n");
3204     }
3205    
3206     /**
3207     * Set the position of the vehicle
3208     *
3209     * @param navit The navit instance
3210     * @param c The coordinate to set as position
3211     * @returns nothing
3212     */
3213    
3214     void
3215     navit_set_position(struct navit *this_, struct pcoord *c)
3216     {
3217     //dbg(0,"EEnter\n");
3218    
3219     if (this_->route) {
3220     route_set_position(this_->route, c);
3221     callback_list_call_attr_0(this_->attr_cbl, attr_position);
3222     }
3223     if (this_->ready == 3)
3224     navit_draw(this_);
3225     }
3226    
3227     static int
3228     navit_set_vehicleprofile(struct navit *this_, char *name)
3229     {
3230     //dbg(0,"EEnter\n");
3231    
3232     struct attr attr;
3233     GList *l;
3234     l=this_->vehicleprofiles;
3235     while (l) {
3236     if (vehicleprofile_get_attr(l->data, attr_name, &attr, NULL)) {
3237     if (!strcmp(attr.u.str, name)) {
3238     this_->vehicleprofile=l->data;
3239     if (this_->route)
3240     route_set_profile(this_->route, this_->vehicleprofile);
3241     return 1;
3242     }
3243     }
3244     l=g_list_next(l);
3245     }
3246     return 0;
3247     }
3248    
3249     static void
3250     navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv)
3251     {
3252     //dbg(0,"EEnter\n");
3253    
3254     struct attr attr;
3255     this_->vehicle=nv;
3256     if (nv && vehicle_get_attr(nv->vehicle, attr_profilename, &attr, NULL)) {
3257     if (navit_set_vehicleprofile(this_, attr.u.str))
3258     return;
3259     }
3260     if (!navit_set_vehicleprofile(this_,"car")) {
3261     /* We do not have a fallback "car" profile
3262     * so lets set any profile */
3263     GList *l;
3264     l=this_->vehicleprofiles;
3265     if (l) {
3266     this_->vehicleprofile=l->data;
3267     if (this_->route)
3268     route_set_profile(this_->route, this_->vehicleprofile);
3269     }
3270     }
3271     }
3272    
3273     /**
3274     * Register a new vehicle
3275     *
3276     * @param navit The navit instance
3277     * @param v The vehicle instance
3278     * @returns 1 for success
3279     */
3280     static int
3281     navit_add_vehicle(struct navit *this_, struct vehicle *v)
3282     {
3283     //dbg(0,"EEnter\n");
3284    
3285     struct navit_vehicle *nv=g_new0(struct navit_vehicle, 1);
3286     struct attr follow, active, animate;
3287     nv->vehicle=v;
3288     nv->follow=0;
3289     nv->last.x = 0;
3290     nv->last.y = 0;
3291     nv->animate_cursor=0;
3292     if ((vehicle_get_attr(v, attr_follow, &follow, NULL)))
3293     nv->follow=follow.u.num;
3294     nv->follow_curr=nv->follow;
3295     this_->vehicles=g_list_append(this_->vehicles, nv);
3296     if ((vehicle_get_attr(v, attr_active, &active, NULL)) && active.u.num)
3297     navit_set_vehicle(this_, nv);
3298     if ((vehicle_get_attr(v, attr_animate, &animate, NULL)))
3299     nv->animate_cursor=animate.u.num;
3300     nv->callback.type=attr_callback;
3301     nv->callback.u.callback=callback_new_attr_2(callback_cast(navit_vehicle_update), attr_position_coord_geo, this_, nv);
3302     vehicle_add_attr(nv->vehicle, &nv->callback);
3303     vehicle_set_attr(nv->vehicle, &this_->self);
3304     return 1;
3305     }
3306    
3307    
3308    
3309    
3310     struct gui *
3311     navit_get_gui(struct navit *this_)
3312     {
3313     return this_->gui;
3314     }
3315    
3316     struct transformation *
3317     navit_get_trans(struct navit *this_)
3318     {
3319     return this_->trans;
3320     }
3321    
3322     struct route *
3323     navit_get_route(struct navit *this_)
3324     {
3325     return this_->route;
3326     }
3327    
3328     struct navigation *
3329     navit_get_navigation(struct navit *this_)
3330     {
3331     return this_->navigation;
3332     }
3333    
3334     struct displaylist *
3335     navit_get_displaylist(struct navit *this_)
3336     {
3337     return this_->displaylist;
3338     }
3339    
3340     void
3341     navit_layout_switch(struct navit *n)
3342     {
3343     //dbg(0,"EEnter\n");
3344    
3345     int currTs=0;
3346     struct attr iso8601_attr,geo_attr,valid_attr,layout_attr;
3347     double trise,tset,trise_actual;
3348     struct layout *l;
3349     int year, month, day;
3350    
3351     if (navit_get_attr(n,attr_layout,&layout_attr,NULL)!=1) {
3352     return; //No layout - nothing to switch
3353     }
3354     if (!n->vehicle)
3355     return;
3356     l=layout_attr.u.layout;
3357    
3358     if (l->dayname || l->nightname) {
3359     //Ok, we know that we have profile to switch
3360    
3361     //Check that we aren't calculating too fast
3362     if (vehicle_get_attr(n->vehicle->vehicle, attr_position_time_iso8601,&iso8601_attr,NULL)==1) {
3363     currTs=iso8601_to_secs(iso8601_attr.u.str);
3364     dbg(1,"currTs: %u:%u\n",currTs%86400/3600,((currTs%86400)%3600)/60);
3365     }
3366     if (currTs-(n->prevTs)<60) {
3367     //We've have to wait a little
3368     return;
3369     }
3370     if (sscanf(iso8601_attr.u.str,"%d-%02d-%02dT",&year,&month,&day) != 3)
3371     return;
3372     if (vehicle_get_attr(n->vehicle->vehicle, attr_position_valid, &valid_attr,NULL) && valid_attr.u.num==attr_position_valid_invalid) {
3373     return; //No valid fix yet
3374     }
3375     if (vehicle_get_attr(n->vehicle->vehicle, attr_position_coord_geo,&geo_attr,NULL)!=1) {
3376     //No position - no sun
3377     return;
3378     }
3379    
3380     //We calculate sunrise anyway, cause it is needed both for day and for night
3381     if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,-5,1,&trise,&tset)!=0) {
3382     //near the pole sun never rises/sets, so we should never switch profiles
3383     dbg(1,"trise: %u:%u, sun never visible, never switch profile\n",HOURS(trise),MINUTES(trise));
3384     n->prevTs=currTs;
3385     return;
3386     }
3387    
3388     trise_actual=trise;
3389     dbg(1,"trise: %u:%u\n",HOURS(trise),MINUTES(trise));
3390     if (l->dayname) {
3391    
3392     if ((HOURS(trise)*60+MINUTES(trise)==(currTs%86400)/60) ||
3393     (n->prevTs==0 && ((HOURS(trise)*60+MINUTES(trise)<(currTs%86400)/60)))) {
3394     //The sun is rising now!
3395     if (strcmp(l->name,l->dayname)) {
3396     navit_set_layout_by_name(n,l->dayname);
3397     }
3398     }
3399     }
3400     if (l->nightname) {
3401     if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,-5,1,&trise,&tset)!=0) {
3402     //near the pole sun never rises/sets, so we should never switch profiles
3403     dbg(1,"tset: %u:%u, sun always visible, never switch profile\n",HOURS(tset),MINUTES(tset));
3404     n->prevTs=currTs;
3405     return;
3406     }
3407     dbg(1,"tset: %u:%u\n",HOURS(tset),MINUTES(tset));
3408     if (HOURS(tset)*60+MINUTES(tset)==((currTs%86400)/60)
3409     || (n->prevTs==0 && (((HOURS(tset)*60+MINUTES(tset)<(currTs%86400)/60)) ||
3410     ((HOURS(trise_actual)*60+MINUTES(trise_actual)>(currTs%86400)/60))))) {
3411     //Time to sleep
3412     if (strcmp(l->name,l->nightname)) {
3413     navit_set_layout_by_name(n,l->nightname);
3414     }
3415     }
3416     }
3417    
3418     n->prevTs=currTs;
3419     }
3420     }
3421    
3422     int
3423     navit_set_vehicle_by_name(struct navit *n,const char *name)
3424     {
3425     //dbg(0,"EEnter\n");
3426    
3427     struct vehicle *v;
3428     struct attr_iter *iter;
3429     struct attr vehicle_attr, name_attr;
3430    
3431     iter=navit_attr_iter_new();
3432    
3433     while (navit_get_attr(n,attr_vehicle,&vehicle_attr,iter)) {
3434     v=vehicle_attr.u.vehicle;
3435     vehicle_get_attr(v,attr_name,&name_attr,NULL);
3436     if (name_attr.type==attr_name) {
3437     if (!strcmp(name,name_attr.u.str)) {
3438     navit_set_attr(n,&vehicle_attr);
3439     navit_attr_iter_destroy(iter);
3440     return 1;
3441     }
3442     }
3443     }
3444     navit_attr_iter_destroy(iter);
3445     return 0;
3446     }
3447    
3448     int
3449     navit_set_layout_by_name(struct navit *n,const char *name)
3450     {
3451     //dbg(0,"EEnter\n");
3452    
3453     struct layout *l;
3454     struct attr_iter iter;
3455     struct attr layout_attr;
3456    
3457     iter.u.list=0x00;
3458    
3459     if (navit_get_attr(n,attr_layout,&layout_attr,&iter)!=1) {
3460     return 0; //No layouts - nothing to do
3461     }
3462     if (iter.u.list==NULL) {
3463     return 0;
3464     }
3465    
3466     iter.u.list=g_list_first(iter.u.list);
3467    
3468     while(iter.u.list) {
3469     l=(struct layout*)iter.u.list->data;
3470     if (!strcmp(name,l->name)) {
3471     layout_attr.u.layout=l;
3472     layout_attr.type=attr_layout;
3473     navit_set_attr(n,&layout_attr);
3474     iter.u.list=g_list_first(iter.u.list);
3475     return 1;
3476     }
3477     iter.u.list=g_list_next(iter.u.list);
3478     }
3479    
3480     iter.u.list=g_list_first(iter.u.list);
3481     return 0;
3482     }
3483    
3484     void
3485     navit_disable_suspend() {
3486     //dbg(0,"EEnter\n");
3487    
3488     gui_disable_suspend(global_navit->gui);
3489     callback_list_call_attr_0(global_navit->attr_cbl,attr_unsuspend);
3490     }
3491    
3492     int
3493     navit_block(struct navit *this_, int block)
3494     {
3495     //dbg(0,"EEnter\n");
3496    
3497     if (block > 0) {
3498     this_->blocked |= 1;
3499     if (graphics_draw_cancel(this_->gra, this_->displaylist))
3500     this_->blocked |= 2;
3501     return 0;
3502     }
3503     if ((this_->blocked & 2) || block < 0) {
3504     this_->blocked=0;
3505     navit_draw(this_);
3506     return 1;
3507     }
3508     this_->blocked=0;
3509     return 0;
3510     }
3511    
3512     void
3513     navit_destroy(struct navit *this_)
3514     {
3515     //dbg(0,"EEnter\n");
3516    
3517     struct mapset*ms;
3518     callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_);
3519    
3520     // dbg(0,"enter");
3521    
3522     /* TODO: destroy objects contained in this_ */
3523     if (this_->vehicle)
3524     vehicle_destroy(this_->vehicle->vehicle);
3525     if (this_->bookmarks)
3526     {
3527     dbg(0,"save position to file");
3528     char *center_file = bookmarks_get_center_file(TRUE);
3529     bookmarks_write_center_to_file(this_->bookmarks, center_file);
3530     g_free(center_file);
3531     bookmarks_destroy(this_->bookmarks);
3532     }
3533     callback_destroy(this_->nav_speech_cb);
3534     callback_destroy(this_->roadbook_callback);
3535     callback_destroy(this_->popup_callback);
3536     callback_destroy(this_->motion_timeout_callback);
3537     callback_destroy(this_->progress_cb);
3538     if(this_->gra)
3539     graphics_remove_callback(this_->gra, this_->resize_callback);
3540     callback_destroy(this_->resize_callback);
3541     if(this_->gra)
3542     graphics_remove_callback(this_->gra, this_->button_callback);
3543     callback_destroy(this_->button_callback);
3544     if(this_->gra)
3545     graphics_remove_callback(this_->gra, this_->motion_callback);
3546     callback_destroy(this_->motion_callback);
3547     if(this_->gra)
3548     graphics_remove_callback(this_->gra, this_->predraw_callback);
3549     callback_destroy(this_->predraw_callback);
3550     route_destroy(this_->route);
3551     ms = navit_get_mapset(this_);
3552     if(ms)
3553     mapset_destroy(ms);
3554     graphics_free(this_->gra);
3555     g_free(this_);
3556     }
3557    
3558     /** @} */

   
Visit the ZANavi Wiki