/[zanavi_public1]/navit/navit/osd/core/osd_core.c
ZANavi

Contents of /navit/navit/osd/core/osd_core.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations) (download)
Tue Aug 11 18:50:37 2015 UTC (8 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 104255 byte(s)
many fixes, and new features
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2008 Navit Team
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     #include "config.h"
21     #ifdef _MSC_VER
22     #define _USE_MATH_DEFINES 1
23     #endif /* _MSC_VER */
24     #include <stdlib.h>
25     #include <math.h>
26     #include <stdio.h>
27     #include <glib.h>
28     #include <time.h>
29     #ifdef HAVE_SYS_TIME_H
30     #include <sys/time.h>
31     #endif
32     #include <string.h>
33     #include "item.h"
34     #include "point.h"
35     #include "coord.h"
36     #include "graphics.h"
37     #include "transform.h"
38     #include "route.h"
39     #include "navit.h"
40     #include "plugin.h"
41     #include "debug.h"
42     #include "callback.h"
43     #include "color.h"
44     #include "vehicle.h"
45     #include "navigation.h"
46     #include "track.h"
47     #include "map.h"
48     #include "file.h"
49     #include "attr.h"
50     #include "command.h"
51     #include "navit_nls.h"
52     #include "messages.h"
53     #include "vehicleprofile.h"
54     #include "roadprofile.h"
55     #include "osd.h"
56     #include "speech.h"
57     #include "event.h"
58     #include "mapset.h"
59     #include "util.h"
60    
61     #ifdef HAVE_API_WIN32_CE
62     #include "libc.h"
63     #endif
64    
65     #ifdef _MSC_VER
66     static double round(double x)
67     {
68     if (x >= 0.0)
69     return floor(x + 0.5);
70     else
71     return ceil(x - 0.5);
72     }
73     #endif /* MSC_VER */
74    
75     struct odometer;
76    
77 zoff99 40
78    
79    
80     int osd_core_item_id_hi = 0;
81     int osd_core_item_id_lo = 0;
82     struct map *osd_core_item_id_map = NULL;
83     char *street_name_save = NULL;
84     char *street_name_systematic_save = NULL;
85    
86    
87     int osd_core_item_id_hi_t = 0;
88     int osd_core_item_id_lo_t = 0;
89     struct map *osd_core_item_id_map_t = NULL;
90     char *street_name_save_t = NULL;
91     char *street_name_systematic_save_t = NULL;
92    
93     char *osd_destination_name = NULL;
94    
95    
96 zoff99 2 static void osd_odometer_reset(struct odometer *this);
97     static void osd_cmd_odometer_reset(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid);
98     static void osd_odometer_draw(struct odometer *this, struct navit *nav, struct vehicle *v);
99     static struct osd_text_item * oti_new(struct osd_text_item * parent);
100    
101     static int b_commandtable_added = 0;
102    
103     struct compass {
104     struct osd_item osd_item;
105     int width;
106     struct graphics_gc *green;
107     };
108    
109     static void
110     transform_rotate(struct point *center, int angle, struct point *p,
111     int count)
112     {
113 zoff99 30 //// dbg(0,,"EEnter\n");
114 zoff99 2
115     int i, x, y;
116     double dx, dy;
117     for (i = 0; i < count; i++) {
118     dx = sin(M_PI * angle / 180.0);
119     dy = cos(M_PI * angle / 180.0);
120     x = dy * p->x - dx * p->y;
121     y = dx * p->x + dy * p->y;
122    
123     p->x = center->x + x;
124     p->y = center->y + y;
125     p++;
126     }
127     }
128    
129     static void
130     handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r,
131     int dir)
132     {
133 zoff99 30 // dbg(0,,"EEnter\n");
134 zoff99 2
135     struct point ph[3];
136     int l = r * 0.4;
137    
138     ph[0].x = 0;
139     ph[0].y = r;
140     ph[1].x = 0;
141     ph[1].y = -r;
142     transform_rotate(p, dir, ph, 2);
143     graphics_draw_lines(gr, gc, ph, 2);
144     ph[0].x = -l;
145     ph[0].y = -r + l;
146     ph[1].x = 0;
147     ph[1].y = -r;
148     ph[2].x = l;
149     ph[2].y = -r + l;
150     transform_rotate(p, dir, ph, 3);
151     graphics_draw_lines(gr, gc, ph, 3);
152     }
153    
154     /**
155     * * Format distance, choosing the unit (m or km) and precision depending on distance
156     * *
157     * * @param distance distance in meters
158     * * @param sep separator character to be inserted between distance value and unit
159     * * @returns a pointer to a string containing the formatted distance
160     * */
161     static char *
162     format_distance(double distance, char *sep, int imperial)
163     {
164 zoff99 30 //// dbg(0,,"EEnter\n");
165 zoff99 2
166     if (imperial){
167     distance *= FEET_PER_METER;
168     if(distance <= 1500){
169     return g_strdup_printf("%.0f%sft", round(distance / 10) * 10, sep);
170     } else {
171     return g_strdup_printf("%.1f%smi", distance / FEET_PER_MILE, sep);
172     }
173     } else {
174     if (distance >= 100000)
175     return g_strdup_printf("%.0f%skm", distance / 1000, sep);
176     else if (distance >= 10000)
177     return g_strdup_printf("%.1f%skm", distance / 1000, sep);
178     else if (distance >= 300)
179     return g_strdup_printf("%.0f%sm", round(distance / 25) * 25, sep);
180     else if (distance >= 50)
181     return g_strdup_printf("%.0f%sm", round(distance / 10) * 10, sep);
182     else if (distance >= 10)
183     return g_strdup_printf("%.0f%sm", distance, sep);
184     else
185     return g_strdup_printf("%.1f%sm", distance, sep);
186     }
187     }
188    
189     /**
190     * * Format time (duration)
191     * *
192     * * @param tm pointer to a tm structure specifying the time
193     * * @param days days
194     * * @returns a pointer to a string containing the formatted time
195     * */
196     static char *
197     format_time(struct tm *tm, int days)
198     {
199     if (days)
200     return g_strdup_printf("%d+%02d:%02d", days, tm->tm_hour, tm->tm_min);
201     else
202     return g_strdup_printf("%02d:%02d", tm->tm_hour, tm->tm_min);
203     }
204    
205     /**
206     * * Format speed in km/h
207     * *
208     * * @param speed speed in km/h
209     * * @param sep separator character to be inserted between speed value and unit
210     * * @returns a pointer to a string containing the formatted speed
211     * */
212     static char *
213     format_speed(double speed, char *sep, char *format, int imperial)
214     {
215     char *unit="km/h";
216     if (imperial) {
217     speed = speed*1000*FEET_PER_METER/FEET_PER_MILE;
218     unit="mph";
219     }
220     if (!format || !strcmp(format,"named"))
221     return g_strdup_printf("%.0f%s%s", speed, sep, unit);
222     else if (!strcmp(format,"value") || !strcmp(format,"unit")) {
223     if (!strcmp(format,"value"))
224     return g_strdup_printf("%.0f", speed);
225     else
226     return g_strdup(unit);
227     }
228     return g_strdup("");
229     }
230    
231     /*static char *
232     format_float(double num)
233     {
234     return g_strdup_printf("%f", num);
235     }*/
236    
237     static char *
238     format_float_0(double num)
239     {
240     return g_strdup_printf("%.0f", num);
241     }
242    
243     /**
244     * sets an attribute (name value pair) of a map item specified by map name and item id
245     *
246     * @param navit The navit instance
247     * @param function unused (needed to match command function signiture)
248     * @param in input attribute in[0] - name of the osd ; in[1] - attr name ; in[2] - attr value
249     * @param out output attribute, 0 on error, 1 on success
250     * @param valid unused
251     * @returns nothing
252     */
253     static void
254     osd_cmd_osd_set_attr(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
255     {
256 zoff99 30 //// dbg(0,,"EEnter\n");
257 zoff99 2
258     struct attr **list;
259     struct attr*val = g_new0(struct attr,1);
260     val->type = attr_type_int_begin;
261     val->u.num = 0;
262     list = g_new0(struct attr *,2);
263     list[0] = val;
264    
265     if (
266     in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str &&//osd name
267     in[1] && ATTR_IS_STRING(in[1]->type) && in[1]->u.str &&//attr_type str
268     in[2] && ATTR_IS_STRING(in[2]->type) && in[2]->u.str //attr_value str
269     ) {
270     struct attr attr_to_set;
271     struct osd* osd;
272    
273     if(ATTR_IS_STRING(attr_from_name(in[1]->u.str))) {
274     attr_to_set.u.str = in[2]->u.str;
275     attr_to_set.type = attr_from_name(in[1]->u.str);
276     }
277     else if(ATTR_IS_INT(attr_from_name(in[1]->u.str))) {
278     attr_to_set.u.num = atoi(in[2]->u.str);
279     attr_to_set.type = attr_from_name(in[1]->u.str);
280     }
281     else if(ATTR_IS_DOUBLE(attr_from_name(in[1]->u.str))) {
282     double* val = g_new0(double,1);
283     *val = atof(in[2]->u.str);
284     attr_to_set.u.numd = val;
285     attr_to_set.type = attr_from_name(in[1]->u.str);
286     }
287     osd = osd_get_osd_by_name(in[0]->u.str);
288     if(osd) {
289     osd_set_attr(osd, &attr_to_set);
290     val->u.num = 1;
291     }
292     }
293     list[1] = NULL;
294     *out = list;
295     }
296    
297    
298    
299     static int odometers_saved = 0;
300     static GList* odometer_list = NULL;
301    
302     static struct command_table commands[] = {
303     {"odometer_reset",command_cast(osd_cmd_odometer_reset)},
304     {"osd_set_attr" ,command_cast(osd_cmd_osd_set_attr)},
305     };
306    
307     struct odometer {
308     struct osd_item osd_item;
309     int width;
310     struct graphics_gc *orange;
311     struct graphics_gc *white;
312     struct callback *click_cb;
313     char *text; //text of label attribute for this osd
314     char *name; //unique name of the odometer (needed for handling multiple odometers persistently)
315     struct color idle_color; //text color when counter is idle
316    
317     int bDisableReset;
318     int bAutoStart;
319     int bActive; //counting or not
320     int autosave_period; //autosave period in seconds
321     double sum_dist; //sum of distance ofprevious intervals in meters
322     double sum_time; //sum of time of previous intervals in seconds (needed for avg spd calculation)
323     double time_all;
324     double last_click_time; //time of last click (for double click handling)
325     double last_start_time; //time of last start of counting
326     double last_update_time; //time of last position update
327     struct coord last_coord;
328     double last_speed;
329     double acceleration;
330     };
331    
332     static void
333     osd_cmd_odometer_reset(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
334     {
335 zoff99 30 //// dbg(0,,"EEnter\n");
336 zoff99 2
337     if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
338     GList* list = odometer_list;
339     while(list) {
340     if(!strcmp(((struct odometer*)(list->data))->name,in[0]->u.str)) {
341     osd_odometer_reset(list->data);
342     osd_odometer_draw(list->data,this,NULL);
343     }
344     list = g_list_next(list);
345     }
346     }
347     }
348    
349     static char*
350     str_replace(char*output, char*input, char*pattern, char*replacement)
351     {
352 zoff99 30 //// dbg(0,,"EEnter\n");
353 zoff99 2
354     char *pos;
355     char *pos2;
356     if (!output || !input || !pattern || !replacement) {
357     return NULL;
358     }
359     if(!strcmp(pattern,"")) {
360     return input;
361     }
362    
363     pos = &input[0];
364     pos2 = &input[0];
365     output[0] = 0;
366     while ( (pos2=strstr(pos,pattern)) ) {
367     strncat(output,pos,pos2-pos);
368     strcat(output,replacement);
369     pos = pos2 + strlen(pattern);
370     }
371     strcat(output,pos);
372     return NULL;
373     }
374    
375     /*
376     * save current odometer state to string
377     */
378     static char *osd_odometer_to_string(struct odometer* this_)
379     {
380     return g_strdup_printf("odometer %s %lf %lf %d\n",this_->name,this_->sum_dist,this_->time_all,this_->bActive);
381     }
382    
383     /*
384     * load current odometer state from string
385     */
386     static void osd_odometer_from_string(struct odometer* this_, char*str)
387     {
388     char* tok;
389     char* name_str;
390     char* sum_dist_str;
391     char* sum_time_str;
392     char* active_str;
393     tok = strtok(str, " ");
394     if( !tok || strcmp("odometer",tok)) {
395     return;
396     }
397     name_str = g_strdup(strtok(NULL, " "));
398     if(!name_str) {
399     return;
400     }
401     sum_dist_str = g_strdup(strtok(NULL, " "));
402     if(!sum_dist_str) {
403     g_free(name_str);
404     return;
405     }
406     sum_time_str = g_strdup(strtok(NULL, " "));
407     if(!sum_time_str) {
408     g_free(name_str);
409     g_free(sum_dist_str);
410     return;
411     }
412     active_str = g_strdup(strtok(NULL, " "));
413     if(!active_str) {
414     g_free(name_str);
415     g_free(sum_dist_str);
416     g_free(sum_time_str);
417     return;
418     }
419     this_->name = name_str;
420     this_->sum_dist = atof(sum_dist_str);
421     this_->sum_time = atof(sum_time_str);
422     this_->bActive = atoi(active_str);
423     this_->last_coord.x = -1;
424     g_free(active_str);
425     g_free(sum_dist_str);
426     g_free(sum_time_str);
427     }
428    
429     static void osd_odometer_draw(struct odometer *this, struct navit *nav, struct vehicle *v)
430     {
431     struct coord curr_coord;
432     struct graphics_gc *curr_color;
433    
434     char *dist_buffer=0;
435     char *spd_buffer=0;
436     char *time_buffer = 0;
437     char *acc_buffer = 0;
438     struct point p, bbox[4];
439     struct attr position_attr,vehicle_attr,imperial_attr,speed_attr;
440     enum projection pro;
441     struct vehicle* curr_vehicle = v;
442     double spd = 0;
443     double curr_spd = 0;
444    
445     int remainder;
446     int days;
447     int hours;
448     int mins;
449     int secs;
450     int imperial=0;
451    
452     char buffer [256+1]="";
453     char buffer2[256+1]="";
454    
455     if(nav) {
456     navit_get_attr(nav, attr_vehicle, &vehicle_attr, NULL);
457     if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
458     imperial=imperial_attr.u.num;
459     }
460     if (vehicle_attr.u.vehicle) {
461     curr_vehicle = vehicle_attr.u.vehicle;
462     }
463    
464     if(0==curr_vehicle)
465     return;
466    
467     osd_std_draw(&this->osd_item);
468     if(this->bActive) {
469     if(!vehicle_get_attr(curr_vehicle, attr_position_coord_geo,&position_attr, NULL)) {
470     return;
471     }
472     pro = projection_mg;//position_attr.u.pcoord->pro;
473     transform_from_geo(pro, position_attr.u.coord_geo, &curr_coord);
474    
475     if (this->last_coord.x != -1 ) {
476     const double cStepDistLimit = 10000;
477     struct timeval tv;
478     double curr_time;
479     double dt;
480     double dCurrDist = 0;
481    
482     gettimeofday(&tv,NULL);
483     curr_time = (double)(tv.tv_usec)/1000000.0+tv.tv_sec;
484     //we have valid previous position
485     dt = curr_time-this->last_update_time;
486     dCurrDist = transform_distance(pro, &curr_coord, &this->last_coord);
487     if(dCurrDist<=cStepDistLimit) {
488     this->sum_dist += dCurrDist;
489     }
490     this->time_all = curr_time-this->last_click_time+this->sum_time;
491     spd = 3.6*(double)this->sum_dist/(double)this->time_all;
492     if(dt != 0) {
493     if (curr_coord.x!=this->last_coord.x || curr_coord.y!=this->last_coord.y) {
494     if(vehicle_get_attr(curr_vehicle, attr_position_speed,&speed_attr, NULL)) {
495     double dv;
496     curr_spd = *speed_attr.u.numd;
497     dv = (curr_spd-this->last_speed)/3.6; //speed difference in m/sec
498     this->acceleration = dv/dt;
499     this->last_speed = curr_spd;
500     this->last_update_time = curr_time;
501     }
502     }
503     }
504     }
505     this->last_coord = curr_coord;
506     }
507    
508     dist_buffer = format_distance(this->sum_dist,"",imperial);
509     spd_buffer = format_speed(spd,"","value",imperial);
510     acc_buffer = g_strdup_printf("%.3f m/s2",this->acceleration);
511     remainder = (int)this->time_all;
512     days = remainder / (24*60*60);
513     remainder = remainder % (24*60*60);
514     hours = remainder / (60*60);
515     remainder = remainder % (60*60);
516     mins = remainder / (60);
517     remainder = remainder % (60);
518     secs = remainder;
519     if(0<days) {
520     time_buffer = g_strdup_printf("%02dd %02d:%02d:%02d",days,hours,mins,secs);
521     }
522     else {
523     time_buffer = g_strdup_printf("%02d:%02d:%02d",hours,mins,secs);
524     }
525    
526     buffer [0] = 0;
527     buffer2[0] = 0;
528     if(this->text) {
529     str_replace(buffer2,this->text,"${avg_spd}",spd_buffer);
530     str_replace(buffer,buffer2,"${distance}",dist_buffer);
531     str_replace(buffer2,buffer,"${time}",time_buffer);
532     str_replace(buffer,buffer2,"${acceleration}",acc_buffer);
533     }
534     g_free(time_buffer);
535    
536     graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
537     p.x=(this->osd_item.w-bbox[2].x)/2;
538     p.y = this->osd_item.h-this->osd_item.h/10;
539     curr_color = this->bActive?this->white:this->orange;
540     graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
541     g_free(dist_buffer);
542     g_free(spd_buffer);
543     g_free(acc_buffer);
544     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
545     }
546    
547    
548     static void
549     osd_odometer_reset(struct odometer *this)
550     {
551     if(!this->bDisableReset) {
552     this->bActive = 0;
553     this->sum_dist = 0;
554     this->sum_time = 0;
555     this->last_start_time = 0;
556     this->last_coord.x = -1;
557     this->last_coord.y = -1;
558     }
559     }
560    
561     static void
562     osd_odometer_click(struct odometer *this, struct navit *nav, int pressed, int button, struct point *p)
563     {
564     struct point bp = this->osd_item.p;
565     struct timeval tv;
566     double curr_time;
567     const double double_click_timewin = .5;
568     osd_wrap_point(&bp, nav);
569     if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h || !this->osd_item.configured ) && !this->osd_item.pressed)
570     return;
571     if (button != 1)
572     return;
573     if (navit_ignore_button(nav))
574     return;
575     if (!!pressed == !!this->osd_item.pressed)
576     return;
577    
578     gettimeofday(&tv,NULL);
579     curr_time = (double)(tv.tv_usec)/1000000.0+tv.tv_sec;
580    
581     if (pressed) { //single click handling
582     if(this->bActive) { //being stopped
583     this->last_coord.x = -1;
584     this->last_coord.y = -1;
585     this->sum_time += curr_time-this->last_click_time;
586     }
587    
588     this->bActive ^= 1; //toggle active flag
589    
590     if (curr_time-double_click_timewin <= this->last_click_time) { //double click handling
591     osd_odometer_reset(this);
592     }
593    
594     this->last_click_time = curr_time;
595    
596     osd_odometer_draw(this, nav,NULL);
597     }
598     }
599    
600    
601     static int
602     osd_odometer_save(struct navit* nav)
603     {
604     //save odometers that are persistent(ie have name)
605     FILE*f;
606     GList* list = odometer_list;
607     char* fn = g_strdup_printf("%s/odometer.txt",navit_get_user_data_directory(TRUE));
608     f = fopen(fn,"w+");
609     g_free(fn);
610     if(!f) {
611     return TRUE;
612     }
613     while (list) {
614     if( ((struct odometer*)(list->data))->name) {
615     char*odo_str = osd_odometer_to_string(list->data);
616     fprintf(f,"%s",odo_str);
617     g_free(odo_str);
618    
619     }
620     list = g_list_next(list);
621     }
622     fclose(f);
623     return TRUE;
624     }
625    
626    
627     static void
628     osd_odometer_init(struct odometer *this, struct navit *nav)
629     {
630     osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
631    
632     this->orange = graphics_gc_new(this->osd_item.gr);
633     graphics_gc_set_foreground(this->orange, &this->idle_color);
634     graphics_gc_set_linewidth(this->orange, this->width);
635    
636     this->white = graphics_gc_new(this->osd_item.gr);
637     graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
638     graphics_gc_set_linewidth(this->white, this->width);
639    
640     graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
641    
642     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_draw), attr_position_coord_geo, this));
643    
644     navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_odometer_click), attr_button, this));
645    
646     if(this->autosave_period>0) {
647     event_add_timeout(this->autosave_period*1000, 1, callback_new_1(callback_cast(osd_odometer_save), NULL));
648     }
649    
650     if(this->bAutoStart) {
651     this->bActive = 1;
652     }
653     osd_odometer_draw(this, nav, NULL);
654     }
655    
656     static void
657     osd_odometer_destroy(struct navit* nav)
658     {
659     if(!odometers_saved) {
660     odometers_saved = 1;
661     osd_odometer_save(NULL);
662     }
663     }
664    
665 zoff99 40 struct osd_priv *
666 zoff99 2 osd_odometer_new(struct navit *nav, struct osd_methods *meth,
667     struct attr **attrs)
668     {
669     FILE* f;
670     char* fn;
671    
672     struct odometer *this = g_new0(struct odometer, 1);
673     struct attr *attr;
674     struct color orange_color={0xffff,0xa5a5,0x0000,0xffff};
675     this->osd_item.p.x = 120;
676     this->osd_item.p.y = 20;
677     this->osd_item.w = 60;
678     this->osd_item.h = 80;
679     this->osd_item.navit = nav;
680     this->osd_item.font_size = 200;
681     this->osd_item.meth.draw = osd_draw_cast(osd_odometer_draw);
682    
683     this->bActive = 0; //do not count on init
684     this->sum_dist = 0;
685     this->last_click_time = time(0);
686     this->last_coord.x = -1;
687     this->last_coord.y = -1;
688    
689     attr = attr_search(attrs, NULL, attr_label);
690     //FIXME find some way to free text!!!!
691     if (attr) {
692     this->text = g_strdup(attr->u.str);
693     }
694     else
695     this->text = NULL;
696    
697     attr = attr_search(attrs, NULL, attr_name);
698     //FIXME find some way to free text!!!!
699     if (attr) {
700     this->name = g_strdup(attr->u.str);
701     }
702     else
703     this->name = NULL;
704    
705     attr = attr_search(attrs, NULL, attr_disable_reset);
706     if (attr)
707     this->bDisableReset = attr->u.num;
708     else
709     this->bDisableReset = 0;
710    
711     attr = attr_search(attrs, NULL, attr_autostart);
712     if (attr)
713     this->bAutoStart = attr->u.num;
714     else
715     this->bAutoStart = 0;
716     attr = attr_search(attrs, NULL, attr_autosave_period);
717     if (attr)
718     this->autosave_period = attr->u.num;
719     else
720     this->autosave_period = -1; //disabled by default
721    
722     osd_set_std_attr(attrs, &this->osd_item, 2);
723     attr = attr_search(attrs, NULL, attr_width);
724     this->width=attr ? attr->u.num : 2;
725     attr = attr_search(attrs, NULL, attr_idle_color);
726     this->idle_color=attr ? *attr->u.color : orange_color; // text idle_color defaults to orange
727    
728     this->last_coord.x = -1;
729     this->last_coord.y = -1;
730     this->sum_dist = 0.0;
731    
732     //load state from file
733     fn = g_strdup_printf("%s/odometer.txt",navit_get_user_data_directory(FALSE));
734     f = fopen(fn,"r+");
735    
736     if(f) {
737     g_free(fn);
738    
739     while(!feof(f)) {
740     char str[128];
741     char *line;
742     if(fgets(str,128,f))
743     {
744     char *tok;
745     line = g_strdup(str);
746     tok = strtok(str," ");
747     if(!strcmp(tok,"odometer")) {
748     tok = strtok(NULL," ");
749     if(this->name && tok && !strcmp(this->name,tok)) {
750     osd_odometer_from_string(this,line);
751     }
752     }
753     g_free(line);
754     }
755     }
756     fclose(f);
757     }
758    
759     if(b_commandtable_added == 0) {
760     navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
761     b_commandtable_added = 1;
762     }
763     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_init), attr_graphics_ready, this));
764     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_destroy), attr_destroy, nav));
765     odometer_list = g_list_append(odometer_list, this);
766    
767     return (struct osd_priv *) this;
768     }
769    
770    
771     struct cmd_interface {
772     struct osd_item osd_item;
773     int width;
774     struct graphics_gc *orange,*white;
775     int update_period; //in sec
776     char* text;
777     struct graphics_image *img;
778     char*img_filename;
779     char* command;
780     int bReserved;
781     };
782    
783     static void
784     osd_cmd_interface_draw(struct cmd_interface *this, struct navit *nav,
785     struct vehicle *v)
786     {
787 zoff99 30 // dbg(0,,"EEnter\n");
788 zoff99 2
789     struct point p;
790     struct point bbox[4];
791     struct graphics_gc *curr_color;
792     struct attr navit;
793     p.x = 0;
794     p.y = 0;
795     navit.type=attr_navit;
796     navit.u.navit = this->osd_item.navit;
797    
798     if(0==this->bReserved) {
799     this->bReserved = 1;
800     command_evaluate(&navit, this->command);
801     this->bReserved = 0;
802     }
803    
804     osd_std_draw(&this->osd_item);
805    
806     //display image
807     if(this->img) {
808     graphics_draw_image(this->osd_item.gr, this->osd_item.graphic_bg, &p, this->img);
809     }
810    
811     //display text
812     graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, this->text, 0x10000, 0, bbox, 0);
813     p.x=(this->osd_item.w-bbox[2].x)/2;
814     p.y = this->osd_item.h-this->osd_item.h/10;
815     curr_color = this->white;
816     if(this->text)
817     graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, this->text, &p, 0x10000, 0);
818     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
819     }
820    
821    
822    
823     static void
824     osd_cmd_interface_init(struct cmd_interface *this, struct navit *nav)
825     {
826 zoff99 30 // dbg(0,,"EEnter\n");
827 zoff99 2
828     osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
829    
830     this->white = graphics_gc_new(this->osd_item.gr);
831     graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
832     graphics_gc_set_linewidth(this->white, this->width);
833    
834    
835     graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
836    
837     if(this->update_period>0) {
838     event_add_timeout(this->update_period*1000, 1, callback_new_1(callback_cast(osd_cmd_interface_draw), this));
839     }
840    
841 zoff99 30 struct callback *cb;
842     cb = callback_new_attr_1(callback_cast (osd_std_click), attr_button, &this->osd_item);
843     callback_add_names(cb, "osd_cmd_interface_init", "osd_std_click");
844     navit_add_callback(nav, cb);
845 zoff99 2
846     this->text = g_strdup("");
847     }
848    
849     static int
850     osd_cmd_interface_set_attr(struct cmd_interface *this_, struct attr* attr)
851     {
852 zoff99 30 //// dbg(0,,"EEnter\n");
853 zoff99 2
854     struct navit* nav;
855     if(NULL==attr || NULL==this_) {
856     return 0;
857     }
858    
859     nav = this_->osd_item.navit;
860    
861     if(attr->type == attr_status_text) {
862     if(this_->text) {
863     g_free(this_->text);
864     }
865     if(attr->u.str) {
866     this_->text = g_strdup(attr->u.str);
867     }
868     return 1;
869     }
870     if(attr->type == attr_src) {
871     if(attr->u.str) {
872     if((!this_->img_filename) || strcmp(this_->img_filename, graphics_icon_path(attr->u.str))) {
873     struct graphics *gra = navit_get_graphics(nav);
874     //destroy old img, create new image
875     if(this_->img) {
876     graphics_image_free(this_->osd_item.gr, this_->img);
877     }
878     if(this_->img_filename) {
879     g_free(this_->img_filename);
880     }
881     this_->img_filename = graphics_icon_path(attr->u.str);
882     this_->img = graphics_image_new(this_->osd_item.gr, this_->img_filename);
883     }
884     }
885     return 1;
886     }
887     return 0;
888     }
889    
890    
891 zoff99 40 struct osd_priv *
892 zoff99 2 osd_cmd_interface_new(struct navit *nav, struct osd_methods *meth,
893     struct attr **attrs)
894     {
895 zoff99 30 // dbg(0,,"EEnter\n");
896 zoff99 2
897     struct cmd_interface *this = g_new0(struct cmd_interface, 1);
898     struct attr *attr;
899    
900     this->osd_item.p.x = 120;
901     this->osd_item.p.y = 20;
902     this->osd_item.w = 60;
903     this->osd_item.h = 80;
904     this->osd_item.navit = nav;
905     this->osd_item.font_size = 200;
906     this->osd_item.meth.draw = osd_draw_cast(osd_cmd_interface_draw);
907    
908     meth->set_attr = osd_cmd_interface_set_attr;
909    
910     osd_set_std_attr(attrs, &this->osd_item, 2);
911    
912     attr = attr_search(attrs, NULL, attr_width);
913     this->width=attr ? attr->u.num : 2;
914    
915     attr = attr_search(attrs, NULL, attr_update_period);
916     this->update_period=attr ? attr->u.num : 5; //default update period is 5 seconds
917    
918     attr = attr_search(attrs, NULL, attr_command);
919     this->command = attr ? g_strdup(attr->u.str) : g_strdup("");
920    
921 zoff99 30 if (b_commandtable_added == 0)
922     {
923 zoff99 2 navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
924     b_commandtable_added = 1;
925     }
926 zoff99 30
927 zoff99 2 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_cmd_interface_init), attr_graphics_ready, this));
928     return (struct osd_priv *) this;
929     }
930    
931    
932    
933    
934     struct stopwatch {
935     struct osd_item osd_item;
936     int width;
937     struct graphics_gc *orange,*white;
938     struct callback *click_cb;
939     struct color idle_color; //text color when counter is idle
940    
941     int bDisableReset;
942     int bActive; //counting or not
943     time_t current_base_time; //base time of currently measured time interval
944     time_t sum_time; //sum of previous time intervals (except current intervals)
945     time_t last_click_time; //time of last click (for double click handling)
946     };
947    
948     static void
949     osd_stopwatch_draw(struct stopwatch *this, struct navit *nav,
950     struct vehicle *v)
951     {
952 zoff99 30 //// dbg(0,,"EEnter\n");
953 zoff99 2
954     struct graphics_gc *curr_color;
955     char buffer[32]="00:00:00";
956     struct point p;
957     struct point bbox[4];
958     time_t total_sec,total_min,total_hours,total_days;
959     total_sec = this->sum_time;
960    
961     osd_std_draw(&this->osd_item);
962    
963     if(this->bActive) {
964     total_sec += time(0)-this->current_base_time;
965     }
966    
967     total_min = total_sec/60;
968     total_hours = total_min/60;
969     total_days = total_hours/24;
970    
971     if (total_days==0) {
972     g_snprintf(buffer,32,"%02d:%02d:%02d", (int)total_hours%24, (int)total_min%60, (int)total_sec%60);
973     } else {
974     g_snprintf(buffer,32,"%02dd %02d:%02d:%02d",
975     (int)total_days, (int)total_hours%24, (int)total_min%60, (int)total_sec%60);
976     }
977    
978     graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
979     p.x=(this->osd_item.w-bbox[2].x)/2;
980     p.y = this->osd_item.h-this->osd_item.h/10;
981    
982     curr_color = this->bActive?this->white:this->orange;
983     graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
984     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
985     }
986    
987    
988     static void
989     osd_stopwatch_click(struct stopwatch *this, struct navit *nav, int pressed, int button, struct point *p)
990     {
991     struct point bp = this->osd_item.p;
992     osd_wrap_point(&bp, nav);
993     if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h || !this->osd_item.configured ) && !this->osd_item.pressed)
994     return;
995     if (button != 1)
996     return;
997     if (navit_ignore_button(nav))
998     return;
999     if (!!pressed == !!this->osd_item.pressed)
1000     return;
1001    
1002     if (pressed) { //single click handling
1003    
1004     if(this->bActive) {
1005     this->sum_time += time(0)-this->current_base_time;
1006     this->current_base_time = 0;
1007     } else {
1008     this->current_base_time = time(0);
1009     }
1010    
1011     this->bActive ^= 1; //toggle active flag
1012    
1013     if (this->last_click_time == time(0) && !this->bDisableReset) { //double click handling
1014     this->bActive = 0;
1015     this->current_base_time = 0;
1016     this->sum_time = 0;
1017     }
1018    
1019     this->last_click_time = time(0);
1020     }
1021    
1022     osd_stopwatch_draw(this, nav,NULL);
1023     }
1024    
1025    
1026     static void
1027     osd_stopwatch_init(struct stopwatch *this, struct navit *nav)
1028     {
1029     osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1030    
1031     this->orange = graphics_gc_new(this->osd_item.gr);
1032     graphics_gc_set_foreground(this->orange, &this->idle_color);
1033     graphics_gc_set_linewidth(this->orange, this->width);
1034    
1035     this->white = graphics_gc_new(this->osd_item.gr);
1036     graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
1037     graphics_gc_set_linewidth(this->white, this->width);
1038    
1039    
1040     graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
1041    
1042     event_add_timeout(500, 1, callback_new_1(callback_cast(osd_stopwatch_draw), this));
1043    
1044     navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_stopwatch_click), attr_button, this));
1045    
1046     osd_stopwatch_draw(this, nav, NULL);
1047     }
1048    
1049 zoff99 40 struct osd_priv *
1050 zoff99 2 osd_stopwatch_new(struct navit *nav, struct osd_methods *meth,
1051     struct attr **attrs)
1052     {
1053     struct stopwatch *this = g_new0(struct stopwatch, 1);
1054     struct attr *attr;
1055     struct color orange_color={0xffff,0xa5a5,0x0000,0xffff};
1056    
1057     this->osd_item.p.x = 120;
1058     this->osd_item.p.y = 20;
1059     this->osd_item.w = 60;
1060     this->osd_item.h = 80;
1061     this->osd_item.navit = nav;
1062     this->osd_item.font_size = 200;
1063     this->osd_item.meth.draw = osd_draw_cast(osd_stopwatch_draw);
1064    
1065     this->bActive = 0; //do not count on init
1066     this->current_base_time = 0;
1067     this->sum_time = 0;
1068     this->last_click_time = 0;
1069    
1070     osd_set_std_attr(attrs, &this->osd_item, 2);
1071     attr = attr_search(attrs, NULL, attr_width);
1072     this->width=attr ? attr->u.num : 2;
1073     attr = attr_search(attrs, NULL, attr_idle_color);
1074     this->idle_color=attr ? *attr->u.color : orange_color; // text idle_color defaults to orange
1075     attr = attr_search(attrs, NULL, attr_disable_reset);
1076     if (attr)
1077     this->bDisableReset = attr->u.num;
1078     else
1079     this->bDisableReset = 0;
1080    
1081     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_stopwatch_init), attr_graphics_ready, this));
1082     return (struct osd_priv *) this;
1083     }
1084    
1085    
1086     static void
1087 zoff99 40 osd_compass_draw(struct compass *this, struct navit *nav, struct vehicle *v)
1088 zoff99 2 {
1089 zoff99 30 // dbg(0,,"EEnter\n");
1090 zoff99 2
1091     struct point p,bbox[4];
1092     struct attr attr_dir, destination_attr, position_attr, imperial_attr;
1093     double dir, vdir = 0;
1094     char *buffer;
1095     struct coord c1, c2;
1096     enum projection pro;
1097     int imperial=0;
1098    
1099     if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
1100 zoff99 40 {
1101     imperial = imperial_attr.u.num;
1102     }
1103 zoff99 2
1104 zoff99 30 //// dbg(0,,"CCC 1\n");
1105 zoff99 2 // **DISABLE** osd_std_draw(&this->osd_item);
1106     // **DISABLE** p.x = this->osd_item.w/2;
1107     // **DISABLE** p.y = this->osd_item.w/2;
1108    
1109     // graphics_send_osd_values(this->osd_item.gr,this->osd_item.graphic_fg_white,"compass","draw_circle","","",0,0,0,0,0.0,0.0,0.0);
1110    
1111     // **DISABLE** graphics_draw_circle(this->osd_item.gr, this->osd_item.graphic_fg_white, &p, this->osd_item.w*5/6);
1112 zoff99 30 //// dbg(0,,"CCC 2\n");
1113 zoff99 40 if (v)
1114     {
1115 zoff99 30 //// dbg(0,,"CCC 3\n");
1116 zoff99 40 if (vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL))
1117     {
1118 zoff99 30 //// dbg(0,,"CCC 4\n");
1119 zoff99 2 vdir = *attr_dir.u.numd;
1120 zoff99 40
1121     #if 1
1122     if (nav->tracking)
1123     {
1124     // double dd;
1125     // dd = tracking_get_direction(nav->tracking);
1126     // dbg(0, "XYZ:vdir:%4.1f tracking:%4.1f\n", (float)vdir, (float)dd);
1127     vdir = tracking_get_direction(nav->tracking);
1128     }
1129     #endif
1130    
1131 zoff99 2 // **DISABLE** handle(this->osd_item.gr, this->osd_item.graphic_fg_white, &p, this->osd_item.w/3, -vdir);
1132     //char *buf_value;
1133     //g_snprintf(buf_value, 20, "%f", -vdir);
1134 zoff99 30 //// dbg(0,,"CCC 5\n");
1135    
1136     #ifdef HAVE_API_ANDROID
1137     send_osd_values("compass","direction","","",(int)-vdir,0,0,0,0,0,0);
1138     #endif
1139 zoff99 2 //g_free(buf_value);
1140 zoff99 30 //// dbg(0,,"CCC 6\n");
1141 zoff99 2 }
1142    
1143 zoff99 30 //// dbg(0,,"CCC 7\n");
1144 zoff99 40 if (navit_get_attr(nav, attr_destination, &destination_attr, NULL) && vehicle_get_attr(v, attr_position_coord_geo,&position_attr, NULL))
1145     {
1146 zoff99 2 pro = destination_attr.u.pcoord->pro;
1147     transform_from_geo(pro, position_attr.u.coord_geo, &c1);
1148     c2.x = destination_attr.u.pcoord->x;
1149     c2.y = destination_attr.u.pcoord->y;
1150     dir = atan2(c2.x - c1.x, c2.y - c1.y) * 180.0 / M_PI;
1151     dir -= vdir;
1152 zoff99 30 //// dbg(0,,"CCC 8\n");
1153 zoff99 2 // **DISABLE** handle(this->osd_item.gr, this->green, &p, this->osd_item.w/3, dir);
1154     buffer=format_distance(transform_distance(pro, &c1, &c2),"",imperial);
1155     // **DISABLE** graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
1156     // **DISABLE** p.x=(this->osd_item.w-bbox[2].x)/2;
1157     // **DISABLE** p.y = this->osd_item.h-this->osd_item.h/10;
1158    
1159 zoff99 30 // // dbg(0,,"dir:%f\n",dir);
1160 zoff99 2 //char *buf_value;
1161     //g_snprintf(buf_value, 20, "%f", dir);
1162 zoff99 30 //// dbg(0,,"CCC 8\n");
1163     #ifdef HAVE_API_ANDROID
1164     send_osd_values("compass","text_and_dst_angle",buffer,"",(int)dir,0,0,0,0,0,0);
1165     #endif
1166     //// dbg(0,,"CCC 10\n");
1167 zoff99 2 //g_free(buf_value);
1168    
1169     // **DISABLE** graphics_draw_text(this->osd_item.gr, this->green, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
1170     g_free(buffer);
1171 zoff99 30 //// dbg(0,,"CCC 11\n");
1172 zoff99 2 }
1173     }
1174    
1175 zoff99 30 //// dbg(0,,"CCC 12\n");
1176 zoff99 2 // **DISABLE** graphics_draw_mode(this->osd_item.gr, draw_mode_end);
1177 zoff99 30 //// dbg(0,,"CCC 13\n");
1178 zoff99 2 }
1179    
1180    
1181    
1182     static void
1183     osd_compass_init(struct compass *this, struct navit *nav)
1184     {
1185 zoff99 30 //struct color c;
1186 zoff99 2
1187 zoff99 30 //// dbg(0,,"CCC 14\n");
1188 zoff99 2
1189 zoff99 30 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1190 zoff99 2
1191 zoff99 30 //// dbg(0,,"CCC 15\n");
1192 zoff99 2
1193 zoff99 30 //this->green = graphics_gc_new(this->osd_item.gr);
1194     //c.r = 0;
1195     //c.g = 65535;
1196     //c.b = 0;
1197     //c.a = 65535;
1198 zoff99 2
1199     // **DISABLE** graphics_gc_set_foreground(this->green, &c);
1200     // **DISABLE** graphics_gc_set_linewidth(this->green, this->width);
1201     // **DISABLE** graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
1202    
1203 zoff99 30 //// dbg(0,,"CCC 16\n");
1204     struct callback *cb;
1205     cb = callback_new_attr_1(callback_cast(osd_compass_draw), attr_position_coord_geo, this);
1206     callback_add_names(cb, "osd_compass_init", "osd_compass_draw");
1207     navit_add_callback(nav, cb);
1208 zoff99 2
1209 zoff99 30 //// dbg(0,,"CCC 17\n");
1210 zoff99 2
1211     osd_compass_draw(this, nav, NULL);
1212    
1213 zoff99 30 //// dbg(0,,"CCC 18\n");
1214 zoff99 2 }
1215    
1216 zoff99 40 struct osd_priv *
1217 zoff99 2 osd_compass_new(struct navit *nav, struct osd_methods *meth,
1218     struct attr **attrs)
1219     {
1220 zoff99 30 //// dbg(0,,"EEnter\n");
1221 zoff99 2
1222     struct compass *this = g_new0(struct compass, 1);
1223     struct attr *attr;
1224     this->osd_item.p.x = 20;
1225     this->osd_item.p.y = 20;
1226     this->osd_item.w = 60;
1227     this->osd_item.h = 80;
1228     this->osd_item.navit = nav;
1229     this->osd_item.font_size = 200;
1230     this->osd_item.meth.draw = osd_draw_cast(osd_compass_draw);
1231     osd_set_std_attr(attrs, &this->osd_item, 2);
1232     attr = attr_search(attrs, NULL, attr_width);
1233     this->width=attr ? attr->u.num : 2;
1234    
1235 zoff99 30 struct callback *cb;
1236     cb = callback_new_attr_1(callback_cast(osd_compass_init), attr_graphics_ready, this);
1237     callback_add_names(cb, "osd_compass_new", "osd_compass_init");
1238     navit_add_callback(nav, cb);
1239 zoff99 2
1240 zoff99 30 // dbg(0,,"11111111111\n");
1241    
1242 zoff99 2 return (struct osd_priv *) this;
1243     }
1244    
1245     struct osd_button {
1246     int use_overlay;
1247     struct osd_item item;
1248     struct callback *draw_cb,*navit_init_cb;
1249     struct graphics_image *img;
1250     char *src;
1251     };
1252    
1253     static void
1254     osd_button_draw(struct osd_button *this, struct navit *nav)
1255     {
1256 zoff99 30 // dbg(0,,"EEnter\n");
1257 zoff99 2
1258     struct point bp = this->item.p;
1259     if (!this->item.configured)
1260     return;
1261     osd_wrap_point(&bp, nav);
1262 zoff99 30 //graphics_draw_image(this->item.gr, this->item.graphic_bg, &bp, this->img);
1263 zoff99 2 }
1264    
1265     static void
1266     osd_button_init(struct osd_button *this, struct navit *nav)
1267     {
1268 zoff99 30 // dbg(0,,"EEnter\n");
1269 zoff99 2
1270     struct graphics *gra = navit_get_graphics(nav);
1271 zoff99 34 //dbg(1, "enter\n");
1272 zoff99 2 this->img = graphics_image_new(gra, this->src);
1273     if (!this->img) {
1274 zoff99 34 //dbg(1, "failed to load '%s'\n", this->src);
1275 zoff99 2 return;
1276     }
1277     if (!this->item.w)
1278     this->item.w=this->img->width;
1279     if (!this->item.h)
1280     this->item.h=this->img->height;
1281     if (this->use_overlay) {
1282     struct graphics_image *img;
1283     struct point p;
1284     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1285     img=graphics_image_new(this->item.gr, this->src);
1286     p.x=(this->item.w-this->img->width)/2;
1287     p.y=(this->item.h-this->img->height)/2;
1288     osd_std_draw(&this->item);
1289     graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
1290     graphics_draw_mode(this->item.gr, draw_mode_end);
1291     graphics_image_free(this->item.gr, img);
1292     } else {
1293     osd_set_std_config(nav, &this->item);
1294     this->item.gr=gra;
1295     this->item.graphic_bg=graphics_gc_new(this->item.gr);
1296     graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_button_draw), attr_postdraw, this, nav));
1297     }
1298     navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_std_click), attr_button, &this->item));
1299     osd_button_draw(this,nav);
1300     }
1301    
1302     int
1303     osd_button_set_attr(struct osd_button *this_, struct attr* attr)
1304     {
1305 zoff99 30 // dbg(0,,"EEnter\n");
1306 zoff99 2
1307     if(NULL==attr || NULL==this_) {
1308     return 0;
1309     }
1310     if(attr->type == attr_src) {
1311     struct navit *nav;
1312     struct graphics *gra;
1313     if(this_->src) {
1314     g_free(this_->src);
1315     }
1316     if(attr->u.str) {
1317     this_->src = graphics_icon_path(attr->u.str);
1318     }
1319     nav = this_->item.navit;
1320     gra = navit_get_graphics(nav);
1321     this_->img = graphics_image_new(gra, this_->src);
1322 zoff99 34 if (!this_->img)
1323     {
1324     //dbg(1, "failed to load '%s'\n", this_->src);
1325 zoff99 2 return 0;
1326     }
1327     if (!this_->item.w)
1328     this_->item.w=this_->img->width;
1329     if (!this_->item.h)
1330     this_->item.h=this_->img->height;
1331    
1332     if (this_->use_overlay) {
1333     struct graphics_image *img;
1334     struct point p;
1335     img=graphics_image_new(this_->item.gr, this_->src);
1336     p.x=(this_->item.w-this_->img->width)/2;
1337     p.y=(this_->item.h-this_->img->height)/2;
1338     osd_std_draw(&this_->item);
1339     graphics_draw_image(this_->item.gr, this_->item.graphic_bg, &p, img);
1340     graphics_image_free(this_->item.gr, img);
1341     }
1342     osd_button_draw(this_,nav);
1343     navit_draw(this_->item.navit);
1344     return 1;
1345     }
1346     return 0;
1347     }
1348    
1349    
1350    
1351 zoff99 40 struct osd_priv *
1352 zoff99 2 osd_button_new(struct navit *nav, struct osd_methods *meth,
1353     struct attr **attrs)
1354     {
1355 zoff99 30 // dbg(0,,"EEnter\n");
1356 zoff99 2
1357     struct osd_button *this = g_new0(struct osd_button, 1);
1358     struct attr *attr;
1359    
1360     this->item.navit = nav;
1361     this->item.meth.draw = osd_draw_cast(osd_button_draw);
1362    
1363     meth->set_attr = osd_button_set_attr;
1364    
1365     osd_set_std_attr(attrs, &this->item, 1|16);
1366    
1367     attr=attr_search(attrs, NULL, attr_use_overlay);
1368     if (attr)
1369     this->use_overlay=attr->u.num;
1370     if (!this->item.command) {
1371 zoff99 30 // dbg(0,, "no command\n");
1372 zoff99 2 goto error;
1373     }
1374     attr = attr_search(attrs, NULL, attr_src);
1375     if (!attr) {
1376 zoff99 30 // dbg(0,, "no src\n");
1377 zoff99 2 goto error;
1378     }
1379    
1380     this->src = graphics_icon_path(attr->u.str);
1381    
1382     navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_button_init), attr_graphics_ready, this));
1383    
1384     if(b_commandtable_added == 0) {
1385     navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
1386     b_commandtable_added = 1;
1387     }
1388    
1389     return (struct osd_priv *) this;
1390     error:
1391     g_free(this);
1392     return NULL;
1393     }
1394    
1395     struct osd_image {
1396     int use_overlay;
1397     struct osd_item item;
1398     struct callback *draw_cb,*navit_init_cb;
1399     struct graphics_image *img;
1400     char *src;
1401     };
1402    
1403     static void
1404     osd_image_draw(struct osd_image *this, struct navit *nav)
1405     {
1406 zoff99 30 // dbg(0,,"EEnter\n");
1407 zoff99 2
1408     struct point bp = this->item.p;
1409     osd_wrap_point(&bp, nav);
1410     graphics_draw_image(this->item.gr, this->item.graphic_bg, &bp, this->img);
1411     }
1412    
1413     static void
1414     osd_image_init(struct osd_image *this, struct navit *nav)
1415     {
1416 zoff99 30 // dbg(0,,"EEnter\n");
1417 zoff99 2
1418     struct graphics *gra = navit_get_graphics(nav);
1419 zoff99 34 //dbg(1, "enter\n");
1420 zoff99 2 this->img = graphics_image_new(gra, this->src);
1421 zoff99 34 if (!this->img)
1422     {
1423     //dbg(1, "failed to load '%s'\n", this->src);
1424 zoff99 2 return;
1425     }
1426     if (!this->item.w)
1427     this->item.w=this->img->width;
1428     if (!this->item.h)
1429     this->item.h=this->img->height;
1430     if (this->use_overlay) {
1431     struct graphics_image *img;
1432     struct point p;
1433     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1434     img=graphics_image_new(this->item.gr, this->src);
1435     p.x=(this->item.w-this->img->width)/2;
1436     p.y=(this->item.h-this->img->height)/2;
1437     osd_std_draw(&this->item);
1438     graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
1439     graphics_draw_mode(this->item.gr, draw_mode_end);
1440     graphics_image_free(this->item.gr, img);
1441     } else {
1442     this->item.configured=1;
1443     this->item.gr=gra;
1444     this->item.graphic_bg=graphics_gc_new(this->item.gr);
1445     graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_button_draw), attr_postdraw, this, nav));
1446     }
1447     osd_image_draw(this,nav);
1448     }
1449    
1450 zoff99 40 struct osd_priv *
1451 zoff99 2 osd_image_new(struct navit *nav, struct osd_methods *meth,
1452     struct attr **attrs)
1453     {
1454 zoff99 30 // dbg(0,,"EEnter\n");
1455 zoff99 2
1456     struct osd_image *this = g_new0(struct osd_image, 1);
1457     struct attr *attr;
1458    
1459     this->item.navit = nav;
1460     this->item.meth.draw = osd_draw_cast(osd_image_draw);
1461    
1462     osd_set_std_attr(attrs, &this->item, 1);
1463    
1464     attr=attr_search(attrs, NULL, attr_use_overlay);
1465     if (attr)
1466     this->use_overlay=attr->u.num;
1467     attr = attr_search(attrs, NULL, attr_src);
1468     if (!attr) {
1469 zoff99 30 // dbg(0,, "no src\n");
1470 zoff99 2 goto error;
1471     }
1472    
1473     this->src = graphics_icon_path(attr->u.str);
1474    
1475     navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_image_init), attr_graphics_ready, this));
1476    
1477     return (struct osd_priv *) this;
1478     error:
1479     g_free(this);
1480     return NULL;
1481     }
1482    
1483     struct nav_next_turn {
1484     struct osd_item osd_item;
1485     char *test_text;
1486     char *icon_src;
1487     int icon_h, icon_w, active;
1488     char *last_name;
1489     int level;
1490 zoff99 40 char *last_destination_name;
1491 zoff99 2 };
1492    
1493     static void
1494 zoff99 40 osd_nav_next_turn_draw(struct nav_next_turn *this, struct navit *navit, struct vehicle *v)
1495 zoff99 2 {
1496     struct point p;
1497     int do_draw = 0;
1498     struct navigation *nav = NULL;
1499     struct map *map = NULL;
1500     struct map_rect *mr = NULL;
1501     struct item *item = NULL;
1502     struct graphics_image *gr_image = NULL;
1503     char *image;
1504     char *name = "unknown";
1505     int level = this->level;
1506 zoff99 40 char *street_destin_text = NULL;
1507 zoff99 2
1508 zoff99 40
1509     // -- WHO writes code in this style ??????
1510     // -- WHO writes code in this style ??????
1511 zoff99 2 if (navit)
1512     nav = navit_get_navigation(navit);
1513     if (nav)
1514     map = navigation_get_map(nav);
1515     if (map)
1516     mr = map_rect_new(map, NULL);
1517     if (mr)
1518     while ((item = map_rect_get_item(mr))
1519     && (item->type == type_nav_position || item->type == type_nav_none || level-- > 0));
1520 zoff99 40 // -- WHO writes code in this style ??????
1521     // -- WHO writes code in this style ??????
1522    
1523    
1524    
1525     if (item)
1526     {
1527 zoff99 2 name = item_to_name(item->type);
1528 zoff99 40
1529     //if (street_destin_text)
1530     //{
1531     // g_free(street_destin_text);
1532     //}
1533    
1534     struct attr attr_l;
1535     if (item_attr_get(item, attr_street_destination, &attr_l))
1536     {
1537     street_destin_text = g_strdup(attr_l.u.str);
1538     }
1539     else
1540     {
1541     street_destin_text = NULL;
1542     }
1543    
1544     int dest_changed = 0;
1545     if ((street_destin_text == NULL) && (this->last_destination_name))
1546     {
1547     dest_changed = 1;
1548     }
1549     else if ((street_destin_text) && (this->last_destination_name == NULL))
1550     {
1551     dest_changed = 1;
1552     }
1553     else if ((street_destin_text) && (this->last_destination_name) && (strcmp(street_destin_text, this->last_destination_name) != 0) )
1554     {
1555     dest_changed = 1;
1556     }
1557    
1558     if (dest_changed == 1)
1559     {
1560     if (osd_destination_name)
1561     {
1562     g_free(osd_destination_name);
1563     osd_destination_name = NULL;
1564     }
1565    
1566     if (street_destin_text)
1567     {
1568     osd_destination_name = g_strdup(street_destin_text);
1569     }
1570     }
1571    
1572     // dbg(0, "DST01:00X:1 sd=%s last=%s %d\n", street_destin_text, this->last_destination_name, dest_changed);
1573    
1574     if (this->active != 1 || this->last_name != name || dest_changed)
1575     {
1576 zoff99 2 this->active = 1;
1577     this->last_name = name;
1578 zoff99 40 if (this->last_destination_name)
1579     {
1580     g_free(this->last_destination_name);
1581     this->last_destination_name = NULL;
1582     }
1583    
1584     if (street_destin_text)
1585     {
1586     this->last_destination_name = g_strdup(street_destin_text);
1587     }
1588     else
1589     {
1590     this->last_destination_name = NULL;
1591     }
1592 zoff99 2 do_draw = 1;
1593     }
1594 zoff99 40 }
1595     else
1596     {
1597     if (this->active != 0)
1598     {
1599 zoff99 2 this->active = 0;
1600     do_draw = 1;
1601     }
1602     }
1603    
1604 zoff99 40 if (do_draw)
1605     {
1606     //dbg(0, "DST01:000a\n");
1607    
1608 zoff99 2 if (this->active)
1609     {
1610 zoff99 40 //dbg(0, "DST01:000b\n");
1611    
1612     #ifdef HAVE_API_ANDROID
1613     android_send_generic_text(3, street_destin_text);
1614     #endif
1615    
1616 zoff99 2 image = g_strdup_printf(this->icon_src, name);
1617    
1618 zoff99 30 #ifdef HAVE_API_ANDROID
1619     send_osd_values("nav_next_turn","draw_image1",image,"",this->icon_w,this->icon_h,0,0,0.0,0.0,0.0);
1620     #endif
1621 zoff99 2
1622 zoff99 40 g_free(image);
1623     }
1624     }
1625 zoff99 2
1626 zoff99 40 if (street_destin_text)
1627     {
1628     g_free(street_destin_text);
1629     }
1630 zoff99 2
1631 zoff99 40 if (mr)
1632     {
1633     map_rect_destroy(mr);
1634     }
1635 zoff99 30
1636 zoff99 2 }
1637    
1638     static void
1639     osd_nav_next_turn_init(struct nav_next_turn *this, struct navit *nav)
1640     {
1641 zoff99 30 // dbg(0,,"EEnter\n");
1642 zoff99 2
1643 zoff99 30 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1644     struct callback *cb;
1645     cb = callback_new_attr_1(callback_cast(osd_nav_next_turn_draw), attr_position_coord_geo, this);
1646     callback_add_names(cb, "osd_nav_next_turn_init", "osd_nav_next_turn_draw");
1647     navit_add_callback(nav, cb);
1648     //navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->osd_item));
1649 zoff99 2 osd_nav_next_turn_draw(this, nav, NULL);
1650     }
1651    
1652 zoff99 40 struct osd_priv *
1653 zoff99 2 osd_nav_next_turn_new(struct navit *nav, struct osd_methods *meth,
1654     struct attr **attrs)
1655     {
1656 zoff99 30 // dbg(0,,"EEnter\n");
1657 zoff99 2
1658     struct nav_next_turn *this = g_new0(struct nav_next_turn, 1);
1659     struct attr *attr;
1660    
1661     this->osd_item.p.x = 20;
1662     this->osd_item.p.y = -80;
1663     this->osd_item.w = 70;
1664     this->osd_item.navit = nav;
1665     this->osd_item.h = 70;
1666     this->osd_item.font_size = 200;
1667     this->osd_item.meth.draw = osd_draw_cast(osd_nav_next_turn_draw);
1668     osd_set_std_attr(attrs, &this->osd_item, 0);
1669    
1670     this->icon_w = -1;
1671     this->icon_h = -1;
1672     this->active = -1;
1673     this->level = 0;
1674    
1675     attr = attr_search(attrs, NULL, attr_icon_w);
1676     if (attr)
1677     this->icon_w = attr->u.num;
1678    
1679     attr = attr_search(attrs, NULL, attr_icon_h);
1680     if (attr)
1681     this->icon_h = attr->u.num;
1682    
1683     attr = attr_search(attrs, NULL, attr_icon_src);
1684 zoff99 31
1685    
1686     if (attr)
1687     {
1688     /*
1689 zoff99 2 struct file_wordexp *we;
1690     char **array;
1691     we = file_wordexp_new(attr->u.str);
1692     array = file_wordexp_get_array(we);
1693     this->icon_src = graphics_icon_path(array[0]);
1694     file_wordexp_destroy(we);
1695 zoff99 31 */
1696    
1697     this->icon_src = graphics_icon_path(attr->u.str);
1698     }
1699     else
1700     {
1701 zoff99 2 this->icon_src = graphics_icon_path("%s_wh.svg");
1702     }
1703 zoff99 31
1704 zoff99 2
1705     attr = attr_search(attrs, NULL, attr_level);
1706     if (attr)
1707 zoff99 30 {
1708 zoff99 2 this->level=attr->u.num;
1709 zoff99 30 }
1710 zoff99 2
1711 zoff99 30 struct callback *cb;
1712     cb = callback_new_attr_1(callback_cast(osd_nav_next_turn_init), attr_graphics_ready, this);
1713     callback_add_names(cb, "osd_nav_next_turn_new", "osd_nav_next_turn_init");
1714     navit_add_callback(nav, cb);
1715    
1716 zoff99 2 return (struct osd_priv *) this;
1717     }
1718    
1719     struct nav_toggle_announcer
1720     {
1721     int w,h;
1722     struct callback *navit_init_cb;
1723     struct osd_item item;
1724     char *icon_src;
1725     int icon_h, icon_w, active, last_state;
1726     };
1727    
1728     static void
1729     osd_nav_toggle_announcer_draw(struct nav_toggle_announcer *this, struct navit *navit, struct vehicle *v)
1730     {
1731     struct point p;
1732     int do_draw = 0;
1733     struct graphics_image *gr_image;
1734     char *path;
1735     char *gui_sound_off = "gui_sound_off";
1736     char *gui_sound_on = "gui_sound";
1737     struct attr attr, speechattr;
1738    
1739     if (this->last_state == -1)
1740     {
1741     if (!navit_get_attr(navit, attr_speech, &speechattr, NULL))
1742     if (!speech_get_attr(speechattr.u.speech, attr_active, &attr, NULL))
1743     attr.u.num = 1;
1744     this->active = attr.u.num;
1745     } else
1746     this->active = !this->active;
1747    
1748     if(this->active != this->last_state)
1749     {
1750     this->last_state = this->active;
1751     do_draw = 1;
1752     }
1753    
1754     if (do_draw)
1755     {
1756     graphics_draw_mode(this->item.gr, draw_mode_begin);
1757     p.x = 0;
1758     p.y = 0;
1759     graphics_draw_rectangle(this->item.gr, this->item.graphic_bg, &p, this->item.w, this->item.h);
1760    
1761     if (this->active)
1762     path = g_strdup_printf(this->icon_src, gui_sound_on);
1763     else
1764     path = g_strdup_printf(this->icon_src, gui_sound_off);
1765    
1766     gr_image = graphics_image_new_scaled(this->item.gr, path, this->icon_w, this->icon_h);
1767     if (!gr_image)
1768     {
1769     g_free(path);
1770     path = graphics_icon_path("unknown.xpm");
1771     gr_image = graphics_image_new_scaled(this->item.gr, path, this->icon_w, this->icon_h);
1772     }
1773    
1774     dbg(1, "gr_image=%p\n", gr_image);
1775    
1776     if (gr_image)
1777     {
1778     p.x = (this->item.w - gr_image->width) / 2;
1779     p.y = (this->item.h - gr_image->height) / 2;
1780     graphics_draw_image(this->item.gr, this->item.graphic_fg_white, &p, gr_image);
1781     graphics_image_free(this->item.gr, gr_image);
1782     }
1783    
1784     g_free(path);
1785     graphics_draw_mode(this->item.gr, draw_mode_end);
1786     }
1787     }
1788    
1789     static void
1790     osd_nav_toggle_announcer_init(struct nav_toggle_announcer *this, struct navit *nav)
1791     {
1792     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1793     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_nav_toggle_announcer_draw), attr_speech, this));
1794     navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->item));
1795     osd_nav_toggle_announcer_draw(this, nav, NULL);
1796     }
1797    
1798 zoff99 40 struct osd_priv *
1799 zoff99 2 osd_nav_toggle_announcer_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
1800     {
1801     struct nav_toggle_announcer *this = g_new0(struct nav_toggle_announcer, 1);
1802     struct attr *attr;
1803     char *command = "announcer_toggle()";
1804    
1805     this->item.w = 48;
1806     this->item.h = 48;
1807     this->item.p.x = -64;
1808     this->item.navit = nav;
1809     this->item.p.y = 76;
1810     this->item.meth.draw = osd_draw_cast(osd_nav_toggle_announcer_draw);
1811    
1812     osd_set_std_attr(attrs, &this->item, 0);
1813    
1814     this->icon_w = -1;
1815     this->icon_h = -1;
1816     this->last_state = -1;
1817    
1818     attr = attr_search(attrs, NULL, attr_icon_src);
1819 zoff99 31
1820     /*
1821 zoff99 2 if (attr) {
1822     struct file_wordexp *we;
1823     char **array;
1824     we = file_wordexp_new(attr->u.str);
1825     array = file_wordexp_get_array(we);
1826     this->icon_src = g_strdup(array[0]);
1827     file_wordexp_destroy(we);
1828     } else
1829     this->icon_src = graphics_icon_path("%s_32.xpm");
1830 zoff99 31 */
1831 zoff99 2
1832     this->item.command = g_strdup(command);
1833    
1834     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_nav_toggle_announcer_init), attr_graphics_ready, this));
1835     return (struct osd_priv *) this;
1836     }
1837    
1838     enum osd_speed_warner_eAnnounceState {eNoWarn=0,eWarningTold=1};
1839     enum camera_t {CAM_FIXED=1, CAM_TRAFFIC_LAMP, CAM_RED, CAM_SECTION, CAM_MOBILE, CAM_RAIL, CAM_TRAFFIPAX};
1840     char*camera_t_strs[] = {"None","Fix","Traffic lamp","Red detect","Section","Mobile","Rail","Traffipax(non persistent)"};
1841     char*camdir_t_strs[] = {"All dir.","UNI-dir","BI-dir"};
1842     enum cam_dir_t {CAMDIR_ALL=0, CAMDIR_ONE, CAMDIR_TWO};
1843    
1844     struct osd_speed_cam_entry {
1845     double lon;
1846     double lat;
1847     enum camera_t cam_type;
1848     int speed_limit;
1849     enum cam_dir_t cam_dir;
1850     int direction;
1851     };
1852    
1853     struct osd_speed_cam {
1854     struct osd_item item;
1855     int width;
1856     struct graphics_gc *white,*orange;
1857     struct graphics_gc *red;
1858     struct color idle_color;
1859    
1860     int announce_on;
1861     enum osd_speed_warner_eAnnounceState announce_state;
1862     char *text; //text of label attribute for this osd
1863     };
1864    
1865     static double
1866     angle_diff(int firstAngle,int secondAngle)
1867     {
1868     double difference = secondAngle - firstAngle;
1869     while (difference < -180) difference += 360;
1870     while (difference > 180) difference -= 360;
1871     return difference;
1872     }
1873    
1874     static void
1875     osd_speed_cam_draw(struct osd_speed_cam *this_, struct navit *navit, struct vehicle *v)
1876     {
1877     struct attr position_attr,vehicle_attr,imperial_attr;
1878     struct point p, bbox[4];
1879     struct attr speed_attr;
1880     struct vehicle* curr_vehicle = v;
1881     struct coord curr_coord;
1882     struct coord cam_coord;
1883     struct mapset* ms;
1884    
1885     double dCurrDist = -1;
1886     int dir_idx = -1;
1887     int dir = -1;
1888     int spd = -1;
1889     int idx = -1;
1890     double speed = -1;
1891     int bFound = 0;
1892    
1893     int dst=2000;
1894     int dstsq=dst*dst;
1895     struct map_selection sel;
1896     struct map_rect *mr;
1897     struct mapset_handle *msh;
1898     struct map *map;
1899     struct item *item;
1900    
1901     struct attr attr_dir;
1902     struct graphics_gc *curr_color;
1903     int ret_attr = 0;
1904     int imperial=0;
1905    
1906     if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
1907     imperial=imperial_attr.u.num;
1908    
1909    
1910     if(navit) {
1911     navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL);
1912     }
1913     else {
1914     return;
1915     }
1916     if (vehicle_attr.u.vehicle) {
1917     curr_vehicle = vehicle_attr.u.vehicle;
1918     }
1919    
1920     if(0==curr_vehicle)
1921     return;
1922    
1923     if(!(ms=navit_get_mapset(navit))) {
1924     return;
1925     }
1926    
1927     ret_attr = vehicle_get_attr(curr_vehicle, attr_position_coord_geo,&position_attr, NULL);
1928     if(0==ret_attr) {
1929     return;
1930     }
1931    
1932     transform_from_geo(projection_mg, position_attr.u.coord_geo, &curr_coord);
1933    
1934     sel.next=NULL;
1935     sel.order=18;
1936     sel.range.min=type_tec_common;
1937     sel.range.max=type_tec_common;
1938     sel.u.c_rect.lu.x=curr_coord.x-dst;
1939     sel.u.c_rect.lu.y=curr_coord.y+dst;
1940     sel.u.c_rect.rl.x=curr_coord.x+dst;
1941     sel.u.c_rect.rl.y=curr_coord.y-dst;
1942    
1943     msh=mapset_open(ms);
1944     while ((map=mapset_next(msh, 1))) {
1945     struct attr attr;
1946     if(map_get_attr(map, attr_type, &attr, NULL)) {
1947     if( strcmp("csv", attr.u.str) && strcmp("binfile", attr.u.str)) {
1948     continue;
1949     }
1950     }
1951     else {
1952     continue;
1953     }
1954     mr=map_rect_new(map, &sel);
1955     if (!mr)
1956     continue;
1957     while ((item=map_rect_get_item(mr))) {
1958     struct coord cn;
1959     if (item->type == type_tec_common && item_coord_get(item, &cn, 1)) {
1960     int dist=transform_distance_sq(&cn, &curr_coord);
1961     if (dist < dstsq) {
1962     struct attr tec_attr;
1963     bFound = 1;
1964     dstsq=dist;
1965     dCurrDist = sqrt(dist);
1966     cam_coord = cn;
1967     idx = -1;
1968     if(item_attr_get(item,attr_tec_type,&tec_attr)) {
1969     idx = tec_attr.u.num;
1970     }
1971     dir_idx = -1;
1972     if(item_attr_get(item,attr_tec_dirtype,&tec_attr)) {
1973     dir_idx = tec_attr.u.num;
1974     }
1975     dir= 0;
1976     if(item_attr_get(item,attr_tec_direction,&tec_attr)) {
1977     dir = tec_attr.u.num;
1978     }
1979     spd= 0;
1980     if(item_attr_get(item,attr_maxspeed,&tec_attr)) {
1981     spd = tec_attr.u.num;
1982     }
1983     }
1984     }
1985     }
1986     map_rect_destroy(mr);
1987     }
1988     mapset_close(msh);
1989    
1990     if(bFound) {
1991     dCurrDist = transform_distance(projection_mg, &curr_coord, &cam_coord);
1992     ret_attr = vehicle_get_attr(curr_vehicle,attr_position_speed,&speed_attr, NULL);
1993     if(0==ret_attr) {
1994     graphics_overlay_disable(this_->item.gr,1);
1995     return;
1996     }
1997     graphics_overlay_disable(this_->item.gr,0);
1998     speed = *speed_attr.u.numd;
1999     if(dCurrDist <= speed*750.0/130.0) { //at speed 130 distance limit is 750m
2000     if(this_->announce_state==eNoWarn && this_->announce_on) {
2001     this_->announce_state=eWarningTold; //warning told
2002     navit_say(navit, _("Look out! Camera!"));
2003     }
2004     }
2005     else {
2006     this_->announce_state=eNoWarn;
2007     }
2008    
2009     if(this_->text) {
2010     char buffer [256]="";
2011     char buffer2[256]="";
2012     char dir_str[16];
2013     char spd_str[16];
2014     buffer [0] = 0;
2015     buffer2[0] = 0;
2016    
2017     osd_std_draw(&this_->item);
2018    
2019     str_replace(buffer,this_->text,"${distance}",format_distance(dCurrDist,"",imperial));
2020     str_replace(buffer2,buffer,"${camera_type}",(0<=idx && idx<=CAM_TRAFFIPAX)?camera_t_strs[idx]:"");
2021     str_replace(buffer,buffer2,"${camera_dir}",(0<=dir_idx && dir_idx<=CAMDIR_TWO)?camdir_t_strs[dir_idx]:"");
2022     sprintf(dir_str,"%d",dir);
2023     sprintf(spd_str,"%d",spd);
2024     str_replace(buffer2,buffer,"${direction}",dir_str);
2025     str_replace(buffer,buffer2,"${speed_limit}",spd_str);
2026    
2027     graphics_get_text_bbox(this_->item.gr, this_->item.font, buffer, 0x10000, 0, bbox, 0);
2028     p.x=(this_->item.w-bbox[2].x)/2;
2029     p.y = this_->item.h-this_->item.h/10;
2030     curr_color = this_->orange;
2031     //tolerance is +-20 degrees
2032     if(
2033     dir_idx==CAMDIR_ONE &&
2034     dCurrDist <= speed*750.0/130.0 &&
2035     vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL) &&
2036     fabs(angle_diff(dir,*attr_dir.u.numd))<=20 ) {
2037     curr_color = this_->red;
2038     }
2039     //tolerance is +-20 degrees in both directions
2040     else if(
2041     dir_idx==CAMDIR_TWO &&
2042     dCurrDist <= speed*750.0/130.0 &&
2043     vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL) &&
2044     (fabs(angle_diff(dir,*attr_dir.u.numd))<=20 || fabs(angle_diff(dir+180,*attr_dir.u.numd))<=20 )) {
2045     curr_color = this_->red;
2046     }
2047     else if(dCurrDist <= speed*750.0/130.0) {
2048     curr_color = this_->red;
2049     }
2050     graphics_draw_text(this_->item.gr, curr_color, NULL, this_->item.font, buffer, &p, 0x10000, 0);
2051     graphics_draw_mode(this_->item.gr, draw_mode_end);
2052     }
2053     }
2054     else {
2055     graphics_overlay_disable(this_->item.gr,1);
2056     }
2057     }
2058    
2059     static void
2060     osd_speed_cam_init(struct osd_speed_cam *this, struct navit *nav)
2061     {
2062     struct color red_color={0xffff,0x0000,0x0000,0xffff};
2063     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
2064    
2065     this->red = graphics_gc_new(this->item.gr);
2066     graphics_gc_set_foreground(this->red, &red_color);
2067     graphics_gc_set_linewidth(this->red, this->width);
2068    
2069     this->orange = graphics_gc_new(this->item.gr);
2070     graphics_gc_set_foreground(this->orange, &this->idle_color);
2071     graphics_gc_set_linewidth(this->orange, this->width);
2072    
2073     this->white = graphics_gc_new(this->item.gr);
2074     graphics_gc_set_foreground(this->white, &this->item.text_color);
2075     graphics_gc_set_linewidth(this->white, this->width);
2076    
2077    
2078     graphics_gc_set_linewidth(this->item.graphic_fg_white, this->width);
2079    
2080     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_cam_draw), attr_position_coord_geo, this));
2081    
2082     }
2083    
2084 zoff99 40 struct osd_priv *
2085 zoff99 2 osd_speed_cam_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
2086     {
2087    
2088     struct color default_color={0xffff,0xa5a5,0x0000,0xffff};
2089    
2090     struct osd_speed_cam *this = g_new0(struct osd_speed_cam, 1);
2091     struct attr *attr;
2092     this->item.p.x = 120;
2093     this->item.p.y = 20;
2094     this->item.w = 60;
2095     this->item.h = 80;
2096     this->item.navit = nav;
2097     this->item.font_size = 200;
2098     this->item.meth.draw = osd_draw_cast(osd_speed_cam_draw);
2099    
2100     osd_set_std_attr(attrs, &this->item, 2);
2101     attr = attr_search(attrs, NULL, attr_width);
2102     this->width=attr ? attr->u.num : 2;
2103     attr = attr_search(attrs, NULL, attr_idle_color);
2104     this->idle_color=attr ? *attr->u.color : default_color; // text idle_color defaults to orange
2105    
2106     attr = attr_search(attrs, NULL, attr_label);
2107     if (attr) {
2108     this->text = g_strdup(attr->u.str);
2109     }
2110     else
2111     this->text = NULL;
2112    
2113     attr = attr_search(attrs, NULL, attr_announce_on);
2114     if (attr) {
2115     this->announce_on = attr->u.num;
2116     }
2117     else {
2118     this->announce_on = 1; //announce by default
2119     }
2120    
2121     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_cam_init), attr_graphics_ready, this));
2122     return (struct osd_priv *) this;
2123     }
2124    
2125     struct osd_speed_warner {
2126     struct osd_item item;
2127     struct graphics_gc *red;
2128     struct graphics_gc *green;
2129     struct graphics_gc *grey;
2130     struct graphics_gc *black;
2131     struct graphics_gc *white;
2132     int width;
2133     int active;
2134     int d;
2135     double speed_exceed_limit_offset;
2136     double speed_exceed_limit_percent;
2137     int announce_on;
2138     enum osd_speed_warner_eAnnounceState announce_state;
2139     int bTextOnly;
2140     struct graphics_image *img_active,*img_passive,*img_off;
2141     char* label_str;
2142     };
2143    
2144     static void
2145     osd_speed_warner_draw(struct osd_speed_warner *this, struct navit *navit, struct vehicle *v)
2146     {
2147     struct point p,bbox[4];
2148     char text[16]="";
2149    
2150     struct tracking *tracking = NULL;
2151     struct graphics_gc *osd_color=this->grey;
2152     struct graphics_image *img = this->img_off;
2153    
2154    
2155     osd_std_draw(&this->item);
2156     p.x=this->item.w/2-this->d/4;
2157     p.y=this->item.h/2-this->d/4;
2158     p.x=this->item.w/2;
2159     p.y=this->item.h/2;
2160    
2161     if (navit) {
2162     tracking = navit_get_tracking(navit);
2163     }
2164     if (tracking) {
2165    
2166     struct attr maxspeed_attr,speed_attr,imperial_attr;
2167     int *flags;
2168     double routespeed = -1;
2169     double tracking_speed = -1;
2170     int osm_data = 0;
2171     struct item *item;
2172     int imperial=0;
2173    
2174     item=tracking_get_current_item(tracking);
2175    
2176     if(navit) {
2177     if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
2178     imperial=imperial_attr.u.num;
2179     }
2180    
2181     flags=tracking_get_current_flags(tracking);
2182 zoff99 34 if (flags && (*flags & NAVIT_AF_SPEED_LIMIT) && tracking_get_attr(tracking, attr_maxspeed, &maxspeed_attr, NULL)) {
2183 zoff99 2 routespeed = maxspeed_attr.u.num;
2184     osm_data = 1;
2185     }
2186     if (routespeed == -1) {
2187     struct vehicleprofile *prof=navit_get_vehicleprofile(navit);
2188     struct roadprofile *rprof=NULL;
2189     if (prof && item)
2190     rprof=vehicleprofile_get_roadprofile(prof, item->type);
2191     if (rprof) {
2192     if(rprof->maxspeed!=0)
2193     routespeed=rprof->maxspeed;
2194     }
2195     }
2196     tracking_get_attr(tracking, attr_position_speed, &speed_attr, NULL);
2197     tracking_speed = *speed_attr.u.numd;
2198     if( -1 != tracking_speed && -1 != routespeed ) {
2199     char*routespeed_str = format_speed(routespeed,"","value",imperial);
2200     g_snprintf(text,16,"%s%s",osm_data ? "" : "~",routespeed_str);
2201     g_free(routespeed_str);
2202     if( this->speed_exceed_limit_offset+routespeed<tracking_speed &&
2203     (100.0+this->speed_exceed_limit_percent)/100.0*routespeed<tracking_speed ) {
2204     if(this->announce_state==eNoWarn && this->announce_on) {
2205     this->announce_state=eWarningTold; //warning told
2206     navit_say(navit,_("Please decrease your speed"));
2207     }
2208     }
2209     if( tracking_speed <= routespeed ) {
2210     this->announce_state=eNoWarn; //no warning
2211     osd_color = this->green;
2212     img = this->img_passive;
2213     }
2214     else {
2215     osd_color = this->red;
2216     img = this->img_active;
2217     }
2218     } else {
2219     osd_color = this->grey;
2220     img = this->img_off;
2221     this->announce_state = eNoWarn;
2222     }
2223     } else {
2224     //when tracking is not available display grey
2225     osd_color = this->grey;
2226     img = this->img_off;
2227     this->announce_state = eNoWarn;
2228     }
2229     if(this->img_active && this->img_passive && this->img_off) {
2230     struct point p;
2231     p.x=(this->item.w-img->width)/2;
2232     p.y=(this->item.h-img->height)/2;
2233     graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
2234     }
2235     else if(0==this->bTextOnly) {
2236     graphics_draw_circle(this->item.gr, osd_color, &p, this->d-this->width*2 );
2237     }
2238     graphics_get_text_bbox(this->item.gr, this->item.font, text, 0x10000, 0, bbox, 0);
2239     p.x=(this->item.w-bbox[2].x)/2;
2240     p.y=(this->item.h+bbox[2].y)/2-bbox[2].y;
2241     graphics_draw_text(this->item.gr, osd_color, NULL, this->item.font, text, &p, 0x10000, 0);
2242     graphics_draw_mode(this->item.gr, draw_mode_end);
2243     }
2244    
2245     static void
2246     osd_speed_warner_init(struct osd_speed_warner *this, struct navit *nav)
2247     {
2248     struct color white_color={0xffff,0xffff,0xffff,0x0000};
2249     struct color red_color={0xffff,0,0,0xffff};
2250     struct color green_color={0,0xffff,0,0xffff};
2251     struct color grey_color={0x8888,0x8888,0x8888,0x8888};
2252     struct color black_color={0x1111,0x1111,0x1111,0x9999};
2253    
2254     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
2255     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_warner_draw), attr_position_coord_geo, this));
2256    
2257     if(this->label_str && !strncmp("images:",this->label_str,7)) {
2258     char *tok1=NULL, *tok2=NULL, *tok3=NULL;
2259     strtok(this->label_str,":");
2260     tok1 = strtok(NULL,":");
2261     if(tok1) {
2262     tok2 = strtok(NULL,":");
2263     }
2264     if(tok1 && tok2) {
2265     tok3 = strtok(NULL,":");
2266     }
2267     if(tok1 && tok2 && tok3) {
2268     tok1 = graphics_icon_path(tok1);
2269     tok2 = graphics_icon_path(tok2);
2270     tok3 = graphics_icon_path(tok3);
2271     this->img_active = graphics_image_new(this->item.gr, tok1);
2272     this->img_passive = graphics_image_new(this->item.gr, tok2);
2273     this->img_off = graphics_image_new(this->item.gr, tok3);
2274     g_free(tok1);
2275     g_free(tok2);
2276     g_free(tok3);
2277     }
2278     }
2279    
2280     g_free(this->label_str);
2281     this->label_str = NULL;
2282    
2283     this->white=graphics_gc_new(this->item.gr);
2284     graphics_gc_set_foreground(this->white, &white_color);
2285    
2286     graphics_gc_set_linewidth(this->white, this->d/2-2 /*-this->width*/ );
2287    
2288     this->red=graphics_gc_new(this->item.gr);
2289     graphics_gc_set_foreground(this->red, &red_color);
2290     graphics_gc_set_linewidth(this->red, this->width);
2291    
2292     this->green=graphics_gc_new(this->item.gr);
2293     graphics_gc_set_foreground(this->green, &green_color);
2294     graphics_gc_set_linewidth(this->green, this->width-2);
2295    
2296     this->grey=graphics_gc_new(this->item.gr);
2297     graphics_gc_set_foreground(this->grey, &grey_color);
2298     graphics_gc_set_linewidth(this->grey, this->width);
2299    
2300     this->black=graphics_gc_new(this->item.gr);
2301     graphics_gc_set_foreground(this->black, &black_color);
2302     graphics_gc_set_linewidth(this->black, this->width);
2303    
2304     osd_speed_warner_draw(this, nav, NULL);
2305     }
2306    
2307 zoff99 40 struct osd_priv *
2308 zoff99 2 osd_speed_warner_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
2309     {
2310     struct osd_speed_warner *this=g_new0(struct osd_speed_warner, 1);
2311     struct attr *attr;
2312     this->item.p.x=-80;
2313     this->item.p.y=20;
2314     this->item.w=60;
2315     this->item.navit = nav;
2316     this->item.h=60;
2317     this->active=-1;
2318     this->item.meth.draw = osd_draw_cast(osd_speed_warner_draw);
2319    
2320     attr = attr_search(attrs, NULL, attr_speed_exceed_limit_offset);
2321     if (attr) {
2322     this->speed_exceed_limit_offset = attr->u.num;
2323     } else
2324     this->speed_exceed_limit_offset = 15; //by default 15 km/h
2325    
2326     attr = attr_search(attrs, NULL, attr_speed_exceed_limit_percent);
2327     if (attr) {
2328     this->speed_exceed_limit_percent = attr->u.num;
2329     } else
2330     this->speed_exceed_limit_percent = 10; //by default factor of 1.1
2331    
2332     this->bTextOnly = 0; //by default display graphics also
2333     attr = attr_search(attrs, NULL, attr_label);
2334     if (attr) {
2335     this->label_str = g_strdup(attr->u.str);
2336     if (!strcmp("text_only",attr->u.str)) {
2337     this->bTextOnly = 1;
2338     }
2339     }
2340    
2341     attr = attr_search(attrs, NULL, attr_announce_on);
2342     if (attr)
2343     this->announce_on = attr->u.num;
2344     else
2345     this->announce_on = 1; //announce by default
2346     osd_set_std_attr(attrs, &this->item, 2);
2347     this->d=this->item.w;
2348     if (this->item.h < this->d)
2349     this->d=this->item.h;
2350     this->width=this->d/10;
2351     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_warner_init), attr_graphics_ready, this));
2352     return (struct osd_priv *) this;
2353     }
2354    
2355     struct osd_text_item {
2356     int static_text;
2357     char *text;
2358     void *prev;
2359     void *next;
2360     enum attr_type section;
2361     enum attr_type attr_typ;
2362     void *root;
2363     int offset;
2364     char *format;
2365     };
2366    
2367     struct osd_text {
2368     struct osd_item osd_item;
2369     int active;
2370     char *text;
2371     int align;
2372     char *last;
2373     struct osd_text_item *items;
2374     };
2375    
2376    
2377     /**
2378     * @brief Format a text attribute
2379     *
2380     * Returns the formatted current value of an attribute as a string
2381     *
2382     * @param attr Pointer to an attr structure specifying the attribute to be formatted
2383     * @param format Pointer to a string specifying how to format the attribute. Allowed format strings depend on the attribute; this member can be NULL.
2384     * @returns Pointer to a string containing the formatted value
2385     */
2386     static char *
2387     osd_text_format_attr(struct attr *attr, char *format, int imperial)
2388     {
2389     struct tm tm, text_tm, text_tm0;
2390     time_t textt;
2391     int days=0;
2392     char buffer[1024];
2393    
2394 zoff99 40 switch (attr->type)
2395     {
2396 zoff99 2 case attr_position_speed:
2397     return format_speed(*attr->u.numd,"",format,imperial);
2398 zoff99 40
2399 zoff99 2 case attr_position_height:
2400     case attr_position_direction:
2401     return format_float_0(*attr->u.numd);
2402 zoff99 40
2403 zoff99 2 case attr_position_magnetic_direction:
2404     return g_strdup_printf("%d",attr->u.num);
2405 zoff99 40
2406 zoff99 2 case attr_position_coord_geo:
2407     if ((!format) || (!strcmp(format,"pos_degminsec")))
2408     {
2409     coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2410     return g_strdup(buffer);
2411     }
2412     else if (!strcmp(format,"pos_degmin"))
2413     {
2414     coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES,buffer,sizeof(buffer));
2415     return g_strdup(buffer);
2416     }
2417     else if (!strcmp(format,"pos_deg"))
2418     {
2419     coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_DECIMAL,buffer,sizeof(buffer));
2420     return g_strdup(buffer);
2421     }
2422     else if (!strcmp(format,"lat_degminsec"))
2423     {
2424     coord_format(attr->u.coord_geo->lat,360,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2425     return g_strdup(buffer);
2426     }
2427     else if (!strcmp(format,"lat_degmin"))
2428     {
2429     coord_format(attr->u.coord_geo->lat,360,DEGREES_MINUTES,buffer,sizeof(buffer));
2430     return g_strdup(buffer);
2431     }
2432     else if (!strcmp(format,"lat_deg"))
2433     {
2434     coord_format(attr->u.coord_geo->lat,360,DEGREES_DECIMAL,buffer,sizeof(buffer));
2435     return g_strdup(buffer);
2436     }
2437     else if (!strcmp(format,"lng_degminsec"))
2438     {
2439     coord_format(360,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2440     return g_strdup(buffer);
2441     }
2442     else if (!strcmp(format,"lng_degmin"))
2443     {
2444     coord_format(360,attr->u.coord_geo->lng,DEGREES_MINUTES,buffer,sizeof(buffer));
2445     return g_strdup(buffer);
2446     }
2447     else if (!strcmp(format,"lng_deg"))
2448     {
2449     coord_format(360,attr->u.coord_geo->lng,DEGREES_DECIMAL,buffer,sizeof(buffer));
2450     return g_strdup(buffer);
2451     }
2452     else
2453     { // fall back to pos_degminsec
2454     coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2455     return g_strdup(buffer);
2456     }
2457 zoff99 40
2458 zoff99 2 case attr_destination_time:
2459     if (!format || (strcmp(format,"arrival") && strcmp(format,"remaining")))
2460     break;
2461 zoff99 40
2462 zoff99 2 textt = time(NULL);
2463     tm = *localtime(&textt);
2464 zoff99 40
2465     if (!strcmp(format,"remaining"))
2466     {
2467 zoff99 2 textt-=tm.tm_hour*3600+tm.tm_min*60+tm.tm_sec;
2468     tm = *localtime(&textt);
2469     }
2470 zoff99 40
2471 zoff99 2 textt += attr->u.num / 10;
2472     text_tm = *localtime(&textt);
2473 zoff99 40
2474     if (tm.tm_year != text_tm.tm_year || tm.tm_mon != text_tm.tm_mon || tm.tm_mday != text_tm.tm_mday)
2475     {
2476 zoff99 2 text_tm0 = text_tm;
2477     text_tm0.tm_sec = 0;
2478     text_tm0.tm_min = 0;
2479     text_tm0.tm_hour = 0;
2480     tm.tm_sec = 0;
2481     tm.tm_min = 0;
2482     tm.tm_hour = 0;
2483     days = (mktime(&text_tm0) - mktime(&tm) + 43200) / 86400;
2484 zoff99 40 }
2485 zoff99 2 return format_time(&text_tm, days);
2486 zoff99 40
2487 zoff99 2 case attr_length:
2488     case attr_destination_length:
2489     if (!format)
2490     break;
2491 zoff99 40
2492 zoff99 2 if (!strcmp(format,"named"))
2493     return format_distance(attr->u.num,"",imperial);
2494 zoff99 40
2495     if (!strcmp(format,"value") || !strcmp(format,"unit"))
2496     {
2497 zoff99 2 char *ret,*tmp=format_distance(attr->u.num," ",imperial);
2498     char *pos=strchr(tmp,' ');
2499     if (! pos)
2500     return tmp;
2501 zoff99 40
2502 zoff99 2 *pos++='\0';
2503     if (!strcmp(format,"value"))
2504     return tmp;
2505 zoff99 40
2506 zoff99 2 ret=g_strdup(pos);
2507     g_free(tmp);
2508 zoff99 40
2509 zoff99 2 return ret;
2510     }
2511     case attr_position_time_iso8601:
2512     if ((!format) || (!strcmp(format,"iso8601")))
2513     {
2514     break;
2515     }
2516     else
2517     {
2518     if (strstr(format, "local;") == format)
2519     {
2520     textt = iso8601_to_secs(attr->u.str);
2521     memcpy ((void *) &tm, (void *) localtime(&textt), sizeof(tm));
2522     strftime(buffer, sizeof(buffer), (char *)(format + 6), &tm);
2523     }
2524     else if ((sscanf(format, "%*c%2d:%2d;", &(text_tm.tm_hour), &(text_tm.tm_min)) == 2) && (strchr("+-", format[0])))
2525     {
2526     if (strchr("-", format[0]))
2527     {
2528     textt = iso8601_to_secs(attr->u.str) - text_tm.tm_hour * 3600 - text_tm.tm_min * 60;
2529     }
2530     else
2531     {
2532     textt = iso8601_to_secs(attr->u.str) + text_tm.tm_hour * 3600 + text_tm.tm_min * 60;
2533     }
2534     memcpy ((void *) &tm, (void *) gmtime(&textt), sizeof(tm));
2535     strftime(buffer, sizeof(buffer), &format[strcspn(format, ";") + 1], &tm);
2536     }
2537     else
2538     {
2539     sscanf(attr->u.str, "%4d-%2d-%2dT%2d:%2d:%2d", &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday), &(tm.tm_hour), &(tm.tm_min), &(tm.tm_sec));
2540     // the tm structure definition is kinda weird and needs some extra voodoo
2541     tm.tm_year-=1900; tm.tm_mon--;
2542     // get weekday and day of the year
2543     mktime(&tm);
2544     strftime(buffer, sizeof(buffer), format, &tm);
2545     }
2546     return g_strdup(buffer);
2547     }
2548     default:
2549     break;
2550     }
2551     return attr_to_text(attr, NULL, 1);
2552     }
2553    
2554     /**
2555     * Parse a string of the form key.subkey or key[index].subkey into its components, where subkey can itself have its own index and further subkeys
2556     *
2557     * @param in String to parse (the part before subkey will be modified by the function); upon returning this pointer will point to a string containing key
2558     * @param index Pointer to an address that will receive a pointer to a string containing index or a null pointer if key does not have an index
2559     * @returns If the function succeeds, a pointer to a string containing subkey, i.e. everything following the first period, or a pointer to an empty string if there is nothing left to parse. If the function fails(index with missing closed bracket or passing a null pointer as index argument when an index was encountered), the return value is NULL
2560     */
2561     static char *
2562     osd_text_split(char *in, char **index)
2563     {
2564     char *pos;
2565     int len;
2566     if (index)
2567     *index=NULL;
2568     len=strcspn(in,"[.");
2569     in+=len;
2570     switch (in[0]) {
2571     case '\0':
2572     return in;
2573     case '.':
2574     *in++='\0';
2575     return in;
2576     case '[':
2577     if (!index)
2578     return NULL;
2579     *in++='\0';
2580     *index=in;
2581     pos=strchr(in,']');
2582     if (pos) {
2583     *pos++='\0';
2584     if (*pos == '.') {
2585     *pos++='\0';
2586     }
2587     return pos;
2588     }
2589     return NULL;
2590     }
2591     return NULL;
2592     }
2593    
2594     static void
2595     osd_text_draw(struct osd_text *this, struct navit *navit, struct vehicle *v)
2596     {
2597    
2598     struct point p, p2[4];
2599     char *str,*last,*next,*value,*absbegin;
2600     char *id_string=NULL;
2601     int do_draw = 0;
2602     struct attr attr, vehicle_attr, maxspeed_attr, imperial_attr;
2603     struct navigation *nav = NULL;
2604     struct tracking *tracking = NULL;
2605     struct route *route = NULL;
2606     struct map *nav_map = NULL;
2607     struct map_rect *nav_mr = NULL;
2608     struct item *item;
2609     struct osd_text_item *oti;
2610     int offset,lines;
2611     int height=this->osd_item.font_size*13/256;
2612     int yspacing=height/2;
2613     int xspacing=height/4;
2614     int imperial=0;
2615    
2616     if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
2617 zoff99 27 {
2618 zoff99 40 imperial = imperial_attr.u.num;
2619 zoff99 27 }
2620 zoff99 2
2621     vehicle_attr.u.vehicle=NULL;
2622     oti=this->items;
2623     str=NULL;
2624    
2625     while (oti)
2626     {
2627    
2628     item=NULL;
2629     value=NULL;
2630     id_string=NULL;
2631    
2632 zoff99 30 if (oti->static_text)
2633     {
2634 zoff99 40 value = g_strdup(oti->text);
2635     id_string = g_strdup("none:static_text:static_text");
2636 zoff99 30 }
2637     else if (oti->section == attr_navigation)
2638     {
2639 zoff99 2 if (navit && !nav)
2640     nav = navit_get_navigation(navit);
2641 zoff99 40
2642 zoff99 2 if (nav && !nav_map)
2643     nav_map = navigation_get_map(nav);
2644 zoff99 40
2645 zoff99 34 if (nav_map)
2646 zoff99 2 nav_mr = map_rect_new(nav_map, NULL);
2647 zoff99 40
2648 zoff99 2 if (nav_mr)
2649     item = map_rect_get_item(nav_mr);
2650    
2651     offset=oti->offset;
2652 zoff99 40
2653     while (item)
2654     {
2655 zoff99 2 if (item->type == type_nav_none)
2656 zoff99 40 {
2657 zoff99 2 item=map_rect_get_item(nav_mr);
2658 zoff99 40 }
2659 zoff99 2 else if (!offset)
2660 zoff99 40 {
2661 zoff99 2 break;
2662 zoff99 40 }
2663     else
2664     {
2665 zoff99 2 offset--;
2666     item=map_rect_get_item(nav_mr);
2667     }
2668     }
2669    
2670 zoff99 40
2671    
2672    
2673    
2674 zoff99 34 if (item)
2675     {
2676 zoff99 40
2677    
2678    
2679    
2680    
2681    
2682    
2683    
2684     if ((osd_core_item_id_hi == item->id_hi) && (osd_core_item_id_lo == item->id_lo) && (osd_core_item_id_map == item->map))
2685     {
2686     if ((oti->attr_typ == attr_street_name) && (street_name_save))
2687     {
2688     value = g_strdup(street_name_save);
2689     }
2690     else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save))
2691     {
2692     value = g_strdup(street_name_systematic_save);
2693     }
2694     else
2695     {
2696     if (item_attr_get(item, oti->attr_typ, &attr))
2697     {
2698     value = osd_text_format_attr(&attr, oti->format, imperial);
2699     }
2700     else
2701     {
2702     // send blank value
2703     value = g_strdup("");
2704     }
2705     }
2706     }
2707     else
2708     {
2709     if ((oti->attr_typ == attr_street_name) || (oti->attr_typ == attr_street_name_systematic))
2710     {
2711     if (item_attr_get(item, attr_street_name, &attr))
2712     {
2713     if (street_name_save)
2714     {
2715     g_free(street_name_save);
2716     }
2717     street_name_save = osd_text_format_attr(&attr, oti->format, imperial);
2718     }
2719     else
2720     {
2721     if (street_name_save)
2722     {
2723     g_free(street_name_save);
2724     }
2725     street_name_save = NULL;
2726     }
2727    
2728     if (item_attr_get(item, attr_street_name_systematic, &attr))
2729     {
2730     if (street_name_systematic_save)
2731     {
2732     g_free(street_name_systematic_save);
2733     }
2734     street_name_systematic_save = osd_text_format_attr(&attr, oti->format, imperial);
2735     }
2736     else
2737     {
2738     if (street_name_systematic_save)
2739     {
2740     g_free(street_name_systematic_save);
2741     }
2742     street_name_systematic_save = NULL;
2743     }
2744    
2745     osd_core_item_id_hi = item->id_hi;
2746     osd_core_item_id_lo = item->id_lo;
2747     osd_core_item_id_map = item->map;
2748    
2749     }
2750    
2751     if (item_attr_get(item, oti->attr_typ, &attr))
2752     {
2753     value = osd_text_format_attr(&attr, oti->format, imperial);
2754     }
2755     else
2756     {
2757     // send blank value
2758     value = g_strdup("");
2759     }
2760     }
2761    
2762    
2763     // -- for navigation use next destination if possible for OSD -----------
2764     if (oti->attr_typ == attr_street_name)
2765     {
2766     if (osd_destination_name)
2767     {
2768     if (value)
2769     {
2770     g_free(value);
2771     value = NULL;
2772     }
2773     value = g_strdup(osd_destination_name);
2774     }
2775     }
2776     else if (oti->attr_typ == attr_street_name_systematic)
2777     {
2778     #if 0
2779     if (osd_destination_name)
2780     {
2781     if (value)
2782     {
2783     g_free(value);
2784     value = NULL;
2785     }
2786     value = g_strdup("");
2787     }
2788     #endif
2789     }
2790     // -- for navigation use next destination if possible for OSD -----------
2791    
2792     id_string = g_strdup_printf("navigation:%s:%s", item_to_name(item->type), attr_to_name(oti->attr_typ));
2793    
2794    
2795 zoff99 41 #ifdef HAVE_API_ANDROID
2796     // -- now dirty hardcoded send time to target in seconds to JAVA --
2797     if (oti->attr_typ == attr_destination_time)
2798     {
2799     // ??? // if (!format || (strcmp(format,"arrival") && strcmp(format,"remaining")))
2800     char *value2 = g_strdup_printf("%d", (int)(attr.u.num / 10)); // time to target in [secs]
2801     send_osd_values("osd_text_draw","draw_text","navigation:nav_position:destination_secs_time",value2 ? value2 : "", 0,0,0,0, 0.0,0.0,0.0);
2802     g_free(value2);
2803     }
2804     #endif
2805    
2806    
2807 zoff99 40 #if 0
2808    
2809    
2810     if ((osd_core_item_id_hi == item->id_hi) && (osd_core_item_id_lo == item->id_lo) && (osd_core_item_id_map == item->map))
2811 zoff99 27 {
2812 zoff99 40 if ((oti->attr_typ == attr_street_name) && (street_name_save))
2813     {
2814     value = g_strdup(street_name_save);
2815     }
2816     else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save))
2817     {
2818     value = g_strdup(street_name_systematic_save);
2819     }
2820     else
2821     {
2822     if (item_attr_get(item, oti->attr_typ, &attr))
2823     {
2824     value = osd_text_format_attr(&attr, oti->format, imperial);
2825     }
2826     }
2827 zoff99 27 }
2828 zoff99 40 else
2829     {
2830     if (item_attr_get(item, oti->attr_typ, &attr))
2831     {
2832     value = osd_text_format_attr(&attr, oti->format, imperial);
2833     }
2834     }
2835    
2836     id_string = g_strdup_printf("navigation:%s:%s", item_to_name(item->type), attr_to_name(oti->attr_typ));
2837    
2838    
2839     if (oti->attr_typ == attr_street_name)
2840     {
2841     osd_core_item_id_hi = item->id_hi;
2842     osd_core_item_id_lo = item->id_lo;
2843     osd_core_item_id_map = item->map;
2844     if (street_name_save)
2845     {
2846     g_free(street_name_save);
2847     }
2848     street_name_save = g_strdup(value);
2849     }
2850     else if (oti->attr_typ == attr_street_name_systematic)
2851     {
2852     osd_core_item_id_hi = item->id_hi;
2853     osd_core_item_id_lo = item->id_lo;
2854     osd_core_item_id_map = item->map;
2855     if (street_name_systematic_save)
2856     {
2857     g_free(street_name_systematic_save);
2858     }
2859     street_name_systematic_save = g_strdup(value);
2860     }
2861    
2862    
2863     #endif
2864    
2865    
2866    
2867 zoff99 2 }
2868 zoff99 34
2869 zoff99 40
2870    
2871    
2872 zoff99 2 if (nav_mr)
2873 zoff99 34 {
2874 zoff99 2 map_rect_destroy(nav_mr);
2875 zoff99 34 }
2876     }
2877     else if (oti->section == attr_vehicle)
2878     {
2879     if (navit && !vehicle_attr.u.vehicle)
2880     {
2881 zoff99 2 navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL);
2882     }
2883 zoff99 34
2884     if (vehicle_attr.u.vehicle)
2885     {
2886     if (vehicle_get_attr(vehicle_attr.u.vehicle, oti->attr_typ, &attr, NULL))
2887     {
2888 zoff99 2 value=osd_text_format_attr(&attr, oti->format, imperial);
2889 zoff99 28 id_string=g_strdup_printf("vehicle:%s:", attr_to_name(oti->attr_typ));
2890 zoff99 2 }
2891     }
2892 zoff99 27 }
2893     else if (oti->section == attr_tracking)
2894     {
2895     if (navit)
2896     {
2897 zoff99 2 tracking = navit_get_tracking(navit);
2898     route = navit_get_route(navit);
2899     }
2900 zoff99 27
2901     if (tracking)
2902     {
2903 zoff99 40 item = tracking_get_current_item(tracking);
2904 zoff99 34
2905 zoff99 27 if (item && (oti->attr_typ == attr_speed))
2906     {
2907 zoff99 2 double routespeed = -1;
2908     int *flags=tracking_get_current_flags(tracking);
2909 zoff99 34 if (flags && (*flags & NAVIT_AF_SPEED_LIMIT) && tracking_get_attr(tracking, attr_maxspeed, &maxspeed_attr, NULL))
2910 zoff99 27 {
2911 zoff99 2 routespeed = maxspeed_attr.u.num;
2912     }
2913 zoff99 27
2914     if (routespeed == -1)
2915     {
2916 zoff99 2 struct vehicleprofile *prof=navit_get_vehicleprofile(navit);
2917     struct roadprofile *rprof=NULL;
2918     if (prof)
2919 zoff99 27 {
2920 zoff99 2 rprof=vehicleprofile_get_roadprofile(prof, item->type);
2921 zoff99 27 }
2922     if (rprof)
2923     {
2924 zoff99 2 routespeed=rprof->speed;
2925     }
2926     }
2927     value = format_speed(routespeed,"", oti->format, imperial);
2928 zoff99 40 id_string=g_strdup("tracking:speed:");
2929 zoff99 27 }
2930     else if (item)
2931     {
2932 zoff99 40
2933     if ((osd_core_item_id_hi_t == item->id_hi) && (osd_core_item_id_lo_t == item->id_lo) && (osd_core_item_id_map_t == item->map))
2934 zoff99 27 {
2935 zoff99 40 if ((oti->attr_typ == attr_street_name) && (street_name_save_t))
2936     {
2937     value = g_strdup(street_name_save_t);
2938     }
2939     else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save_t))
2940     {
2941     value = g_strdup(street_name_systematic_save_t);
2942     }
2943     else
2944     {
2945     if (tracking_get_attr(tracking, oti->attr_typ, &attr, NULL))
2946     {
2947     value = osd_text_format_attr(&attr, oti->format, imperial);
2948     }
2949     else
2950     {
2951     // send blank value
2952     value = g_strdup("");
2953     }
2954     }
2955 zoff99 27 }
2956 zoff99 28 else
2957     {
2958 zoff99 40 if ((oti->attr_typ == attr_street_name) || (oti->attr_typ == attr_street_name_systematic))
2959     {
2960     if (tracking_get_attr(tracking, attr_street_name, &attr, NULL))
2961     {
2962     if (street_name_save_t)
2963     {
2964     g_free(street_name_save_t);
2965     }
2966     street_name_save_t = osd_text_format_attr(&attr, oti->format, imperial);
2967     }
2968     else
2969     {
2970     if (street_name_save_t)
2971     {
2972     g_free(street_name_save_t);
2973     }
2974     street_name_save_t = NULL;
2975     }
2976    
2977     if (tracking_get_attr(tracking, attr_street_name_systematic, &attr, NULL))
2978     {
2979     if (street_name_systematic_save_t)
2980     {
2981     g_free(street_name_systematic_save_t);
2982     }
2983     street_name_systematic_save_t = osd_text_format_attr(&attr, oti->format, imperial);
2984     }
2985     else
2986     {
2987     if (street_name_systematic_save_t)
2988     {
2989     g_free(street_name_systematic_save_t);
2990     }
2991     street_name_systematic_save_t = NULL;
2992     }
2993    
2994     osd_core_item_id_hi_t = item->id_hi;
2995     osd_core_item_id_lo_t = item->id_lo;
2996     osd_core_item_id_map_t = item->map;
2997    
2998     }
2999    
3000     if (tracking_get_attr(tracking, oti->attr_typ, &attr, NULL))
3001     {
3002     value=osd_text_format_attr(&attr, oti->format, imperial);
3003     }
3004     else
3005     {
3006     // send blank value
3007     value=g_strdup("");
3008     }
3009 zoff99 28 }
3010 zoff99 40
3011     id_string=g_strdup_printf("tracking:%s:", attr_to_name(oti->attr_typ));
3012 zoff99 2 }
3013     }
3014 zoff99 27 }
3015     else if (oti->section == attr_navit)
3016     {
3017     if (oti->attr_typ == attr_message)
3018     {
3019 zoff99 2 struct message *msg;
3020     int len,offset;
3021     char *tmp;
3022    
3023     msg = navit_get_messages(navit);
3024     len = 0;
3025 zoff99 40
3026     while (msg)
3027     {
3028 zoff99 2 len+= strlen(msg->text) + 2;
3029    
3030     msg = msg->next;
3031     }
3032    
3033     value = g_malloc(len +1);
3034    
3035     msg = navit_get_messages(navit);
3036     offset = 0;
3037 zoff99 40
3038     while (msg)
3039     {
3040 zoff99 2 tmp = g_stpcpy((value+offset), msg->text);
3041     g_stpcpy(tmp, "\\n");
3042     offset += strlen(msg->text) + 2;
3043    
3044     msg = msg->next;
3045     }
3046    
3047     value[len] = '\0';
3048     }
3049     }
3050    
3051     // id_string=g_strdup_printf("%s#+#%s:%s",id_string, str ? str:"",value ? value:" ");
3052 zoff99 30
3053     #ifdef HAVE_API_ANDROID
3054     send_osd_values("osd_text_draw","draw_text",id_string,value ? value : "", 0,0,0,0, 0.0,0.0,0.0);
3055     #endif
3056     //// dbg(0,,"%s\n",id_string);
3057 zoff99 2 if (id_string)
3058 zoff99 27 {
3059 zoff99 2 g_free(id_string);
3060 zoff99 27 }
3061 zoff99 2
3062     next=g_strdup_printf("%s%s",str ? str:"",value ? value:" ");
3063 zoff99 40
3064 zoff99 2 if (value)
3065     g_free(value);
3066 zoff99 40
3067 zoff99 2 if (str)
3068     g_free(str);
3069 zoff99 40
3070 zoff99 2 str=next;
3071     oti=oti->next;
3072     }
3073    
3074 zoff99 27 if ( this->last && str && !strcmp(this->last, str) )
3075     {
3076 zoff99 2 do_draw=0;
3077 zoff99 27 }
3078     else
3079     {
3080 zoff99 2 do_draw=1;
3081 zoff99 40
3082 zoff99 2 if (this->last)
3083     g_free(this->last);
3084 zoff99 40
3085 zoff99 2 this->last = g_strdup(str);
3086     }
3087    
3088     absbegin=str;
3089 zoff99 27 if (do_draw)
3090     {
3091 zoff99 2 // **DISABLE** osd_std_draw(&this->osd_item);
3092     }
3093     if (do_draw && str)
3094     {
3095     lines=0;
3096     next=str;
3097     last=str;
3098     while ((next=strstr(next, "\\n"))) {
3099     last = next;
3100     lines++;
3101     next++;
3102     }
3103    
3104     while (*last) {
3105     if (! g_ascii_isspace(*last)) {
3106     lines++;
3107     break;
3108     }
3109     last++;
3110     }
3111    
3112 zoff99 27 // dbg(1,"this->align=%d\n", this->align);
3113     switch (this->align & 51)
3114     {
3115 zoff99 2 case 1:
3116     p.y=0;
3117     break;
3118     case 2:
3119     p.y=(this->osd_item.h-lines*(height+yspacing)-yspacing);
3120     break;
3121     case 16: // Grow from top to bottom
3122     p.y = 0;
3123     if (lines != 0) {
3124     this->osd_item.h = (lines-1) * (height+yspacing) + height;
3125     } else {
3126     this->osd_item.h = 0;
3127     }
3128    
3129 zoff99 27 if (do_draw)
3130     {
3131 zoff99 30 //osd_std_resize(&this->osd_item);
3132 zoff99 2 }
3133     default:
3134     p.y=(this->osd_item.h-lines*(height+yspacing)-yspacing)/2;
3135     }
3136    
3137     while (str)
3138     {
3139     next=strstr(str, "\\n");
3140 zoff99 27 if (next)
3141     {
3142 zoff99 2 *next='\0';
3143     next+=2;
3144     }
3145 zoff99 30
3146     /*
3147 zoff99 2 graphics_get_text_bbox(this->osd_item.gr,
3148     this->osd_item.font,
3149     str, 0x10000,
3150     0x0, p2, 0);
3151 zoff99 30 */
3152    
3153     /*
3154 zoff99 27 switch (this->align & 12)
3155     {
3156 zoff99 2 case 4:
3157     p.x=xspacing;
3158     break;
3159     case 8:
3160     p.x=this->osd_item.w-(p2[2].x-p2[0].x)-xspacing;
3161     break;
3162     default:
3163     p.x = ((p2[0].x - p2[2].x) / 2) + (this->osd_item.w / 2);
3164     }
3165     p.y += height+yspacing;
3166 zoff99 30 */
3167 zoff99 2
3168     // graphics_send_osd_values(this->osd_item.gr, this->osd_item.graphic_fg_text,"osd_text_draw","draw_text",str,"", 0,0,0,0, 0.0,0.0,0.0);
3169    
3170     // **DISABLE**
3171     /*
3172     graphics_draw_text(this->osd_item.gr,
3173     this->osd_item.graphic_fg_text,
3174     NULL, this->osd_item.font,
3175     str, &p, 0x10000,
3176     0);
3177     */
3178     str=next;
3179     }
3180     }
3181 zoff99 27
3182     if (do_draw)
3183     {
3184 zoff99 2 // **DISABLE** graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3185     }
3186     g_free(absbegin);
3187     }
3188    
3189     /**
3190     * @brief Create a new osd_text_item and insert it into a linked list
3191     *
3192     * @param parent Pointer to the preceding osd_text_item structure in the list. If NULL, the new osd_text_item becomes the root element of a new list.
3193     * @returns A pointer to the new osd_text_item element.
3194     */
3195     static struct osd_text_item *
3196     oti_new(struct osd_text_item * parent)
3197     {
3198 zoff99 30 // dbg(0,,"EEnter\n");
3199 zoff99 2
3200     struct osd_text_item *this;
3201     this=g_new0(struct osd_text_item, 1);
3202     this->prev=parent;
3203    
3204     if(!parent) {
3205     this->root=this;
3206     } else {
3207     parent->next=this;
3208     this->root=parent->root;
3209     }
3210    
3211     return this;
3212     }
3213    
3214     /**
3215     * @brief Prepare a text type OSD element
3216     *
3217     * Parses the label string (as specified in the XML file) for a text type OSD element into attributes and static text.
3218     *
3219     * @param this Pointer to an osd_text structure representing the OSD element. The items member of this structure will receive a pointer to a list of osd_text_item structures.
3220     * @param nav Pointer to a navit structure
3221     * @returns nothing
3222     */
3223     static void
3224     osd_text_prepare(struct osd_text *this, struct navit *nav)
3225     {
3226 zoff99 30 // dbg(0,,"EEnter\n");
3227 zoff99 2
3228     char *absbegin,*str,*start,*end,*key,*subkey,*index;
3229     struct osd_text_item *oti;
3230    
3231     oti=NULL;
3232     str=g_strdup(this->text);
3233     absbegin=str;
3234    
3235     while ((start=strstr(str, "${"))) {
3236    
3237     *start='\0';
3238     start+=2;
3239    
3240     // find plain text before
3241     if (start!=str) {
3242     oti = oti_new(oti);
3243     oti->static_text=1;
3244     oti->text=g_strdup(str);
3245    
3246     }
3247    
3248     end=strstr(start,"}");
3249     if (! end)
3250     break;
3251    
3252     *end++='\0';
3253     key=start;
3254    
3255     subkey=osd_text_split(key,NULL);
3256    
3257     oti = oti_new(oti);
3258     oti->section=attr_from_name(key);
3259    
3260     if (( oti->section == attr_navigation ||
3261     oti->section == attr_tracking) && subkey) {
3262     key=osd_text_split(subkey,&index);
3263    
3264     if (index)
3265     oti->offset=atoi(index);
3266    
3267     subkey=osd_text_split(key,&index);
3268    
3269     if (!strcmp(key,"route_speed")) {
3270     oti->attr_typ=attr_speed;
3271     } else {
3272     oti->attr_typ=attr_from_name(key);
3273     }
3274     oti->format = g_strdup(index);
3275    
3276     } else if ((oti->section == attr_vehicle || oti->section == attr_navit) && subkey) {
3277     key=osd_text_split(subkey,&index);
3278     if (!strcmp(subkey,"messages")) {
3279     oti->attr_typ=attr_message;
3280     } else {
3281     oti->attr_typ=attr_from_name(subkey);
3282     }
3283     oti->format = g_strdup(index);
3284     }
3285    
3286 zoff99 30 switch(oti->attr_typ)
3287     {
3288     struct callback *cb;
3289    
3290 zoff99 2 default:
3291 zoff99 30 cb = callback_new_attr_1(callback_cast(osd_text_draw), attr_position_coord_geo, this);
3292     callback_add_names(cb, "osd_text_prepare", "osd_text_draw");
3293     navit_add_callback(nav, cb);
3294 zoff99 2 break;
3295     }
3296    
3297     str=(end);
3298     }
3299    
3300     if(*str!='\0'){
3301     oti = oti_new(oti);
3302     oti->static_text=1;
3303     oti->text=g_strdup(str);
3304     }
3305    
3306     if (oti)
3307     this->items=oti->root;
3308     else
3309     this->items=NULL;
3310    
3311     g_free(absbegin);
3312    
3313     }
3314    
3315     static void
3316     osd_text_init(struct osd_text *this, struct navit *nav)
3317     {
3318 zoff99 30 // dbg(0,,"EEnter\n");
3319 zoff99 2
3320 zoff99 30 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3321    
3322     struct callback *cb;
3323     cb = callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->osd_item);
3324     callback_add_names(cb, "osd_text_init", "osd_std_click");
3325     navit_add_callback(nav, cb);
3326    
3327 zoff99 2 osd_text_prepare(this,nav);
3328     osd_text_draw(this, nav, NULL);
3329     }
3330    
3331 zoff99 40 struct osd_priv *
3332 zoff99 2 osd_text_new(struct navit *nav, struct osd_methods *meth,
3333     struct attr **attrs)
3334     {
3335     struct osd_text *this = g_new0(struct osd_text, 1);
3336     struct attr *attr;
3337    
3338     this->osd_item.p.x = -80;
3339     this->osd_item.p.y = 20;
3340     this->osd_item.w = 60;
3341     this->osd_item.h = 20;
3342     this->osd_item.navit = nav;
3343     this->osd_item.font_size = 200;
3344     this->osd_item.meth.draw = osd_draw_cast(osd_text_draw);
3345     osd_set_std_attr(attrs, &this->osd_item, 2);
3346    
3347     this->active = -1;
3348     this->last = NULL;
3349    
3350     attr = attr_search(attrs, NULL, attr_label);
3351     if (attr)
3352     this->text = g_strdup(attr->u.str);
3353     else
3354     this->text = NULL;
3355 zoff99 40
3356 zoff99 2 attr = attr_search(attrs, NULL, attr_align);
3357 zoff99 40
3358 zoff99 2 if (attr)
3359     this->align=attr->u.num;
3360    
3361     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_text_init), attr_graphics_ready, this));
3362 zoff99 40
3363 zoff99 2 return (struct osd_priv *) this;
3364     }
3365    
3366     struct gps_status {
3367     struct osd_item osd_item;
3368     char *icon_src;
3369     int icon_h, icon_w, active;
3370     int strength;
3371     };
3372    
3373     static void
3374     osd_gps_status_draw(struct gps_status *this, struct navit *navit,
3375     struct vehicle *v)
3376     {
3377     struct point p;
3378     int do_draw = 0;
3379     struct graphics_image *gr_image;
3380     char *image;
3381     struct attr attr, vehicle_attr;
3382     int strength=-1;
3383    
3384     if (navit && navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL)) {
3385     if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_fix_type, &attr, NULL)) {
3386     switch(attr.u.num) {
3387     case 1:
3388     case 2:
3389     strength=2;
3390     if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_sats_used, &attr, NULL)) {
3391     dbg(1,"num=%d\n", attr.u.num);
3392     if (attr.u.num >= 3)
3393     strength=attr.u.num-1;
3394     if (strength > 5)
3395     strength=5;
3396     if (strength > 3) {
3397     if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_hdop, &attr, NULL)) {
3398     if (*attr.u.numd > 2.0 && strength > 4)
3399     strength=4;
3400     if (*attr.u.numd > 4.0 && strength > 3)
3401     strength=3;
3402     }
3403     }
3404     }
3405     break;
3406     default:
3407     strength=1;
3408     }
3409     }
3410     }
3411     if (this->strength != strength) {
3412     this->strength=strength;
3413     do_draw=1;
3414     }
3415     if (do_draw) {
3416     osd_std_draw(&this->osd_item);
3417     if (this->active) {
3418     image = g_strdup_printf(this->icon_src, strength);
3419     gr_image = graphics_image_new_scaled(this->osd_item.gr, image, this->icon_w, this->icon_h);
3420     if (gr_image) {
3421     p.x = (this->osd_item.w - gr_image->width) / 2;
3422     p.y = (this->osd_item.h - gr_image->height) / 2;
3423     graphics_draw_image(this->osd_item.gr, this->osd_item. graphic_fg_white, &p, gr_image);
3424     graphics_image_free(this->osd_item.gr, gr_image);
3425     }
3426     g_free(image);
3427     }
3428     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3429     }
3430     }
3431    
3432     static void
3433     osd_gps_status_init(struct gps_status *this, struct navit *nav)
3434     {
3435     osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3436     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_gps_status_draw), attr_position_coord_geo, this));
3437     osd_gps_status_draw(this, nav, NULL);
3438     }
3439    
3440 zoff99 40 struct osd_priv *
3441 zoff99 2 osd_gps_status_new(struct navit *nav, struct osd_methods *meth,
3442     struct attr **attrs)
3443     {
3444     struct gps_status *this = g_new0(struct gps_status, 1);
3445     struct attr *attr;
3446    
3447     this->osd_item.p.x = 20;
3448     this->osd_item.p.y = -80;
3449     this->osd_item.w = 60;
3450     this->osd_item.navit = nav;
3451     this->osd_item.h = 40;
3452     this->osd_item.font_size = 200;
3453     this->osd_item.meth.draw = osd_draw_cast(osd_gps_status_draw);
3454     osd_set_std_attr(attrs, &this->osd_item, 0);
3455    
3456     this->icon_w = -1;
3457     this->icon_h = -1;
3458     this->active = -1;
3459     this->strength = -2;
3460    
3461     attr = attr_search(attrs, NULL, attr_icon_w);
3462     if (attr)
3463     this->icon_w = attr->u.num;
3464    
3465     attr = attr_search(attrs, NULL, attr_icon_h);
3466     if (attr)
3467     this->icon_h = attr->u.num;
3468    
3469     attr = attr_search(attrs, NULL, attr_icon_src);
3470 zoff99 31 /*
3471 zoff99 2 if (attr) {
3472     struct file_wordexp *we;
3473     char **array;
3474     we = file_wordexp_new(attr->u.str);
3475     array = file_wordexp_get_array(we);
3476     this->icon_src = g_strdup(array[0]);
3477     file_wordexp_destroy(we);
3478     } else
3479     this->icon_src = graphics_icon_path("gui_strength_%d_32_32.png");
3480 zoff99 31 */
3481 zoff99 2
3482     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_gps_status_init), attr_graphics_ready, this));
3483     return (struct osd_priv *) this;
3484     }
3485    
3486    
3487     struct volume {
3488     struct osd_item osd_item;
3489     char *icon_src;
3490     int icon_h, icon_w, active;
3491     int strength;
3492     struct callback *click_cb;
3493     };
3494    
3495     static void
3496     osd_volume_draw(struct volume *this, struct navit *navit)
3497     {
3498     struct point p;
3499     struct graphics_image *gr_image;
3500     char *image;
3501    
3502     osd_std_draw(&this->osd_item);
3503     if (this->active) {
3504     image = g_strdup_printf(this->icon_src, this->strength);
3505     gr_image = graphics_image_new_scaled(this->osd_item.gr, image, this->icon_w, this->icon_h);
3506     if (gr_image) {
3507     p.x = (this->osd_item.w - gr_image->width) / 2;
3508     p.y = (this->osd_item.h - gr_image->height) / 2;
3509     graphics_draw_image(this->osd_item.gr, this->osd_item. graphic_fg_white, &p, gr_image);
3510     graphics_image_free(this->osd_item.gr, gr_image);
3511     }
3512     g_free(image);
3513     }
3514     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3515     }
3516    
3517     static void
3518     osd_volume_click(struct volume *this, struct navit *nav, int pressed, int button, struct point *p)
3519     {
3520     struct point bp = this->osd_item.p;
3521     osd_wrap_point(&bp, nav);
3522     if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h) && !this->osd_item.pressed)
3523     return;
3524     navit_ignore_button(nav);
3525     if (pressed) {
3526     if (p->y - bp.y < this->osd_item.h/2)
3527     this->strength++;
3528     else
3529     this->strength--;
3530     if (this->strength < 0)
3531     this->strength=0;
3532     if (this->strength > 5)
3533     this->strength=5;
3534     osd_volume_draw(this, nav);
3535     }
3536     }
3537     static void
3538     osd_volume_init(struct volume *this, struct navit *nav)
3539     {
3540     osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3541     navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_volume_click), attr_button, this));
3542     osd_volume_draw(this, nav);
3543     }
3544    
3545 zoff99 40 struct osd_priv *
3546 zoff99 2 osd_volume_new(struct navit *nav, struct osd_methods *meth,
3547     struct attr **attrs)
3548     {
3549     struct volume *this = g_new0(struct volume, 1);
3550     struct attr *attr;
3551    
3552     this->osd_item.p.x = 20;
3553     this->osd_item.p.y = -80;
3554     this->osd_item.w = 60;
3555     this->osd_item.navit = nav;
3556     this->osd_item.h = 40;
3557     this->osd_item.font_size = 200;
3558     this->osd_item.meth.draw = osd_draw_cast(osd_volume_draw);
3559     osd_set_std_attr(attrs, &this->osd_item, 0);
3560    
3561     this->icon_w = -1;
3562     this->icon_h = -1;
3563     this->active = -1;
3564     this->strength = -1;
3565    
3566     attr = attr_search(attrs, NULL, attr_icon_w);
3567     if (attr)
3568     this->icon_w = attr->u.num;
3569    
3570     attr = attr_search(attrs, NULL, attr_icon_h);
3571     if (attr)
3572     this->icon_h = attr->u.num;
3573    
3574     attr = attr_search(attrs, NULL, attr_icon_src);
3575 zoff99 31
3576     /*
3577 zoff99 2 if (attr) {
3578     struct file_wordexp *we;
3579     char **array;
3580     we = file_wordexp_new(attr->u.str);
3581     array = file_wordexp_get_array(we);
3582     this->icon_src = g_strdup(array[0]);
3583     file_wordexp_destroy(we);
3584     } else
3585     this->icon_src = graphics_icon_path("gui_strength_%d_32_32.png");
3586 zoff99 31 */
3587 zoff99 2
3588     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_volume_init), attr_graphics_ready, this));
3589     return (struct osd_priv *) this;
3590     }
3591    
3592     struct osd_scale {
3593     int use_overlay;
3594     struct osd_item item;
3595     struct callback *draw_cb,*navit_init_cb;
3596     struct graphics_gc *black;
3597     };
3598    
3599     static void
3600     osd_scale_draw(struct osd_scale *this, struct navit *nav)
3601     {
3602 zoff99 30 // dbg(0,,"EEnter\n");
3603 zoff99 2
3604     struct point bp,bp1,bp2;
3605     struct point p[10],bbox[4];
3606     struct coord c[2];
3607     struct attr transformation, imperial_attr;
3608     int len;
3609     double dist,exp,base,man;
3610     char *text;
3611     int w=this->item.w*9/10;
3612     int o=(this->item.w-w)/2;
3613     int imperial=0;
3614    
3615     if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
3616     imperial=imperial_attr.u.num;
3617    
3618     if (!navit_get_attr(nav, attr_transformation, &transformation, NULL))
3619     return;
3620     if (this->use_overlay)
3621     {
3622     // **DISABLE** graphics_draw_mode(this->item.gr, draw_mode_begin);
3623     bp.x=0;
3624     bp.y=0;
3625    
3626 zoff99 30 #ifdef HAVE_API_ANDROID
3627     send_osd_values("scale","draw_rectangle1","","",this->item.w, this->item.h,0,0,0.0,0.0,0.0);
3628     #endif
3629 zoff99 2 // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_bg, &bp, this->item.w, this->item.h);
3630     } else {
3631     bp=this->item.p;
3632     osd_wrap_point(&bp, nav);
3633     }
3634     bp1=bp;
3635     bp1.y+=this->item.h/2;
3636     bp1.x+=o;
3637     bp2=bp1;
3638     bp2.x+=w;
3639     p[0]=bp1;
3640     p[1]=bp2;
3641     transform_reverse(transformation.u.transformation, &p[0], &c[0]);
3642     transform_reverse(transformation.u.transformation, &p[1], &c[1]);
3643     dist=transform_distance(transform_get_projection(transformation.u.transformation), &c[0], &c[1]);
3644     exp=floor(log10(dist));
3645     base=pow(10,exp);
3646     man=dist/base;
3647     if (man >= 5)
3648     man=5;
3649     else if (man >= 2)
3650     man=2;
3651     else
3652     man=1;
3653     len=this->item.w-man*base/dist*w;
3654     p[0].x+=len/2;
3655     p[1].x-=len/2;
3656     p[2]=p[0];
3657     p[3]=p[0];
3658     p[2].y-=this->item.h/10;
3659     p[3].y+=this->item.h/10;
3660     p[4]=p[1];
3661     p[5]=p[1];
3662     p[4].y-=this->item.h/10;
3663     p[5].y+=this->item.h/10;
3664     p[6]=p[2];
3665     p[6].x-=2;
3666     p[6].y-=2;
3667     p[7]=p[0];
3668     p[7].y-=2;
3669     p[8]=p[4];
3670     p[8].x-=2;
3671     p[8].y-=2;
3672    
3673 zoff99 30 #ifdef HAVE_API_ANDROID
3674     send_osd_values("scale","draw_rectangle2","","",len,this->item.h,0,0,0.0,0.0,0.0);
3675     #endif
3676 zoff99 2
3677     // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+6, 4,this->item.h/5+4);
3678     // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+7, p[1].x-p[0].x, 4);
3679     // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+8, 4,this->item.h/5+4);
3680     // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p, 2);
3681     // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p+2, 2);
3682     // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p+4, 2);
3683     text=format_distance(man*base, "", imperial);
3684     graphics_get_text_bbox(this->item.gr, this->item.font, text, 0x10000, 0, bbox, 0);
3685     p[0].x=(this->item.w-bbox[2].x)/2+bp.x;
3686     p[0].y=bp.y+this->item.h-this->item.h/10;
3687    
3688 zoff99 30 #ifdef HAVE_API_ANDROID
3689     send_osd_values("scale","draw_text",text,"",0,0,0,0,0.0,0.0,0.0);
3690     #endif
3691 zoff99 2
3692     // **DISABLE** graphics_draw_text(this->item.gr, this->black, this->item.graphic_fg_white, this->item.font, text, &p[0], 0x10000, 0);
3693     g_free(text);
3694     if (this->use_overlay)
3695     {
3696     // **DISABLE** graphics_draw_mode(this->item.gr, draw_mode_end);
3697     }
3698     }
3699    
3700     static void
3701     osd_scale_init(struct osd_scale *this, struct navit *nav)
3702     {
3703 zoff99 30 // dbg(0,,"EEnter\n");
3704    
3705     /*
3706 zoff99 2 struct color color_white={0xffff,0xffff,0xffff,0x0000};
3707     struct color color_black={0x0000,0x0000,0x0000,0x0000};
3708     struct graphics *gra = navit_get_graphics(nav);
3709     dbg(1, "enter\n");
3710     if (this->use_overlay) {
3711     osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
3712     } else {
3713     this->item.configured=1;
3714     this->item.gr=gra;
3715     this->item.font = graphics_font_new(this->item.gr, this->item.font_size, 1);
3716     this->item.graphic_fg_white=graphics_gc_new(this->item.gr);
3717     this->item.color_white=color_white;
3718     graphics_gc_set_foreground(this->item.graphic_fg_white, &this->item.color_white);
3719     }
3720     this->black=graphics_gc_new(this->item.gr);
3721     graphics_gc_set_foreground(this->black, &color_black);
3722     graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_scale_draw), attr_postdraw, this, nav));
3723     if (navit_get_ready(nav) == 3)
3724     osd_scale_draw(this, nav);
3725 zoff99 30
3726     */
3727 zoff99 2 }
3728    
3729 zoff99 40 struct osd_priv *
3730 zoff99 2 osd_scale_new(struct navit *nav, struct osd_methods *meth,
3731     struct attr **attrs)
3732     {
3733 zoff99 30
3734     // dbg(0,,"EEnter\n");
3735    
3736 zoff99 2 struct osd_scale *this = g_new0(struct osd_scale, 1);
3737     struct attr *attr;
3738    
3739     this->item.navit = nav;
3740     this->item.meth.draw = osd_draw_cast(osd_scale_draw);
3741    
3742     osd_set_std_attr(attrs, &this->item, 3);
3743    
3744     attr=attr_search(attrs, NULL, attr_use_overlay);
3745     if (attr)
3746     this->use_overlay=attr->u.num;
3747    
3748 zoff99 30 // navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_scale_init), attr_graphics_ready, this));
3749 zoff99 2
3750     return (struct osd_priv *) this;
3751     }
3752    
3753     struct auxmap {
3754     struct osd_item osd_item;
3755     struct displaylist *displaylist;
3756     struct transformation *ntrans;
3757     struct transformation *trans;
3758     struct layout *layout;
3759     struct callback *postdraw_cb;
3760     struct graphics_gc *red;
3761     struct navit *nav;
3762     };
3763    
3764     static void
3765     osd_auxmap_draw(struct auxmap *this)
3766     {
3767     int d=10;
3768     struct point p;
3769     struct attr mapset;
3770    
3771     if (!this->osd_item.configured)
3772     return;
3773     if (!navit_get_attr(this->nav, attr_mapset, &mapset, NULL) || !mapset.u.mapset)
3774     return;
3775     p.x=this->osd_item.w/2;
3776     p.y=this->osd_item.h/2;
3777     transform_set_center(this->trans, transform_get_center(this->ntrans));
3778     transform_set_scale(this->trans, 64);
3779     transform_set_yaw(this->trans, transform_get_yaw(this->ntrans));
3780     transform_setup_source_rect(this->trans);
3781     transform_set_projection(this->trans, transform_get_projection(this->ntrans));
3782     #if 0
3783     graphics_displaylist_draw(this->osd_item.gr, this->displaylist, this->trans, this->layout, 4);
3784     #endif
3785     graphics_draw(this->osd_item.gr, this->displaylist, mapset.u.mapset, this->trans, this->layout, 0, NULL, 1);
3786     graphics_draw_circle(this->osd_item.gr, this->red, &p, d);
3787     graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3788    
3789     }
3790    
3791     static void
3792     osd_auxmap_init(struct auxmap *this, struct navit *nav)
3793     {
3794 zoff99 30 // dbg(0,,"EEnter\n");
3795    
3796    
3797 zoff99 2 struct graphics *gra;
3798     struct attr attr;
3799     struct map_selection sel;
3800     struct color red={0xffff,0x0,0x0,0xffff};
3801    
3802     this->nav=nav;
3803     if (! navit_get_attr(nav, attr_graphics, &attr, NULL))
3804     return;
3805     gra=attr.u.graphics;
3806     graphics_add_callback(gra, callback_new_attr_1(callback_cast(osd_auxmap_draw), attr_postdraw, this));
3807     if (! navit_get_attr(nav, attr_transformation, &attr, NULL))
3808     return;
3809     this->ntrans=attr.u.transformation;
3810     if (! navit_get_attr(nav, attr_displaylist, &attr, NULL))
3811     return;
3812     this->displaylist=attr.u.displaylist;
3813     if (! navit_get_attr(nav, attr_layout, &attr, NULL))
3814     return;
3815     this->layout=attr.u.layout;
3816     osd_set_std_graphic(nav, &this->osd_item, NULL);
3817     graphics_init(this->osd_item.gr);
3818     this->red=graphics_gc_new(gra);
3819     graphics_gc_set_foreground(this->red,&red);
3820     graphics_gc_set_linewidth(this->red,3);
3821     this->trans=transform_new();
3822     memset(&sel, 0, sizeof(sel));
3823     sel.u.p_rect.rl.x=this->osd_item.w;
3824     sel.u.p_rect.rl.y=this->osd_item.h;
3825     transform_set_screen_selection(this->trans, &sel);
3826     graphics_set_rect(this->osd_item.gr, &sel.u.p_rect);
3827     #if 0
3828     osd_auxmap_draw(this, nav);
3829     #endif
3830     }
3831    
3832 zoff99 40 struct osd_priv *
3833 zoff99 2 osd_auxmap_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
3834     {
3835     struct auxmap *this = g_new0(struct auxmap, 1);
3836    
3837     this->osd_item.p.x = 20;
3838     this->osd_item.p.y = -80;
3839     this->osd_item.w = 60;
3840     this->osd_item.h = 40;
3841     this->osd_item.font_size = 200;
3842     osd_set_std_attr(attrs, &this->osd_item, 0);
3843    
3844     navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_auxmap_init), attr_navit, this));
3845     return (struct osd_priv *) this;
3846     }
3847    
3848 zoff99 40 #ifdef PLUGSSS
3849 zoff99 2 void
3850     plugin_init(void)
3851     {
3852 zoff99 31 //dbg(0,"osd plugin init\n");
3853 zoff99 2 plugin_register_osd_type("compass", osd_compass_new);
3854 zoff99 31 //dbg(0,"osd 1\n");
3855 zoff99 2 plugin_register_osd_type("navigation_next_turn", osd_nav_next_turn_new);
3856 zoff99 31 //dbg(0,"osd 2\n");
3857 zoff99 2 plugin_register_osd_type("button", osd_button_new);
3858 zoff99 31 //dbg(0,"osd 3\n");
3859 zoff99 30 plugin_register_osd_type("toggle_announcer", osd_nav_toggle_announcer_new);
3860 zoff99 31 //dbg(0,"osd 4\n");
3861 zoff99 30 plugin_register_osd_type("speed_warner", osd_speed_warner_new);
3862 zoff99 31 //dbg(0,"osd 5\n");
3863 zoff99 30 plugin_register_osd_type("speed_cam", osd_speed_cam_new);
3864 zoff99 31 //dbg(0,"osd 6\n");
3865 zoff99 30 plugin_register_osd_type("text", osd_text_new);
3866 zoff99 31 //dbg(0,"osd 7\n");
3867 zoff99 30 plugin_register_osd_type("gps_status", osd_gps_status_new);
3868 zoff99 31 //dbg(0,"osd 8\n");
3869 zoff99 30 plugin_register_osd_type("volume", osd_volume_new);
3870 zoff99 31 //dbg(0,"osd 10\n");
3871 zoff99 30 plugin_register_osd_type("scale", osd_scale_new);
3872 zoff99 31 //dbg(0,"osd 11\n");
3873 zoff99 2 plugin_register_osd_type("image", osd_image_new);
3874 zoff99 31 //dbg(0,"osd 12\n");
3875 zoff99 2 plugin_register_osd_type("stopwatch", osd_stopwatch_new);
3876 zoff99 31 //dbg(0,"osd 13\n");
3877 zoff99 2 plugin_register_osd_type("odometer", osd_odometer_new);
3878 zoff99 31 //dbg(0,"osd 14\n");
3879 zoff99 2 plugin_register_osd_type("auxmap", osd_auxmap_new);
3880 zoff99 31 //dbg(0,"osd 15\n");
3881 zoff99 2 plugin_register_osd_type("cmd_interface", osd_cmd_interface_new);
3882 zoff99 31 //dbg(0,"osd ready\n");
3883 zoff99 2 }
3884 zoff99 40 #endif
3885 zoff99 30

   
Visit the ZANavi Wiki