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

Contents of /navit/navit/navit.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki