Fix:Core:Correct attribute alloc and free
[navit-package] / navit / osd.c
1 /**
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 <glib.h>
21 #include "debug.h"
22 #include "plugin.h"
23 #include "item.h"
24 #include "color.h"
25 #include "point.h"
26 #include "navit.h"
27 #include "graphics.h"
28 #include "command.h"
29 #include "callback.h"
30 #include "osd.h"
31
32
33 struct osd {
34         struct osd_methods meth;
35         struct osd_priv *priv;
36 };
37
38 struct osd *
39 osd_new(struct attr *parent, struct attr **attrs)
40 {
41         struct osd *o;
42         struct osd_priv *(*new)(struct navit *nav, struct osd_methods *meth, struct attr **attrs);
43         struct attr *type=attr_search(attrs, NULL, attr_type);
44
45         if (! type)
46                 return NULL;
47         new=plugin_get_osd_type(type->u.str);
48         if (! new)
49                 return NULL;
50         o=g_new0(struct osd, 1);
51         o->priv=new(parent->u.navit, &o->meth, attrs);
52         return o;
53 }
54
55 void
56 osd_wrap_point(struct point *p, struct navit *nav)
57 {
58         if (p->x < 0)
59                 p->x += navit_get_width(nav);
60         if (p->y < 0)
61                 p->y += navit_get_height(nav);
62
63 }
64
65 void
66 osd_std_click(struct osd_item *this, struct navit *nav, int pressed, int button, struct point *p)
67 {
68         struct point bp = this->p;
69         osd_wrap_point(&bp, nav);
70         if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->w || p->y > bp.y + this->h || !this->configured) && !this->pressed)
71                 return;
72         if (navit_ignore_button(nav))
73                 return;
74         this->pressed = pressed;
75         if (pressed && this->command) {
76                 struct attr navit;
77                 navit.type=attr_navit;
78                 navit.u.navit=nav;
79                 dbg(0, "calling command '%s'\n", this->command);
80                 command_evaluate(&navit, this->command);
81         }
82 }
83
84 void
85 osd_std_resize(struct osd_item *item)
86 {
87         graphics_overlay_resize(item->gr, &item->p, item->w, item->h, 65535, 1);
88 }
89  
90 static void
91 osd_std_calculate_sizes(struct osd_item *item, struct osd_priv *priv, int w, int h) 
92 {
93         struct attr vehicle_attr;
94
95         if (item->rel_w) {
96                 item->w = (item->rel_w * w) / 100;
97         }
98  
99         if (item->rel_h) {
100                 item->h = (item->rel_h * h) / 100;
101         }
102  
103         if (item->rel_x) {
104                 item->p.x = (item->rel_x * w) / 100;
105         }
106  
107         if (item->rel_y) {
108                 item->p.y = (item->rel_y * h) / 100;
109         }
110
111         osd_std_resize(item);
112         if (item->meth.draw) {
113                 if (navit_get_attr(item->navit, attr_vehicle, &vehicle_attr, NULL)) {
114                         item->meth.draw(priv, item->navit, vehicle_attr.u.vehicle);
115                 }
116         }
117 }
118
119 static void
120 osd_std_reconfigure(struct osd_item *item, struct command_saved *cs)
121 {
122         if (!command_saved_error(cs)) {
123                 graphics_overlay_disable(item->gr, !command_saved_get_int(cs));
124         } else {
125                 dbg(0, "Error in saved command: %i\n", command_saved_error(cs));
126         }
127 }
128
129 void
130 osd_set_std_attr(struct attr **attrs, struct osd_item *item, int flags)
131 {
132         struct attr *attr;
133
134         item->flags=flags;
135         item->osd_configuration=-1;
136         item->color_white.r = 0xffff;
137         item->color_white.g = 0xffff;
138         item->color_white.b = 0xffff;
139         item->color_white.a = 0xffff;
140         item->text_color.r = 0xffff;
141         item->text_color.g = 0xffff;
142         item->text_color.b = 0xffff;
143         item->text_color.a = 0xffff;
144         if (flags & 1) {
145                 item->color_bg.r = 0x0808;
146                 item->color_bg.g = 0x0808;
147                 item->color_bg.b = 0xf8f8;
148                 item->color_bg.a = 0x0000;
149         } else {
150                 item->color_bg.r = 0x0;
151                 item->color_bg.g = 0x0;
152                 item->color_bg.b = 0x0;
153                 item->color_bg.a = 0x5fff;
154         }
155
156         attr=attr_search(attrs, NULL, attr_osd_configuration);
157         if (attr)
158                 item->osd_configuration = attr->u.num;
159
160         attr=attr_search(attrs, NULL, attr_enable_expression);
161         if (attr) {
162                 item->enable_cs = command_saved_new(attr->u.str, item->navit, NULL);
163         }
164
165         attr = attr_search(attrs, NULL, attr_w);
166         if (attr) {
167                 if (attr->u.num > ATTR_REL_MAXABS) {
168                         item->rel_w = attr->u.num - ATTR_REL_RELSHIFT;
169                 } else {
170                         item->rel_w = 0;
171                         item->w = attr->u.num;
172                 }
173         }
174
175         attr = attr_search(attrs, NULL, attr_h);
176         if (attr) {
177                 if (attr->u.num > ATTR_REL_MAXABS) {
178                         item->rel_h = attr->u.num - ATTR_REL_RELSHIFT;
179                 } else {
180                         item->rel_h = 0;
181                         item->h = attr->u.num;
182                 }
183         }
184
185         attr = attr_search(attrs, NULL, attr_x);
186         if (attr) {
187                 if (attr->u.num > ATTR_REL_MAXABS) {
188                         item->rel_x = attr->u.num - ATTR_REL_RELSHIFT;
189                 } else {
190                         item->rel_x = 0;
191                         item->p.x = attr->u.num;
192                 }
193         }
194
195         attr = attr_search(attrs, NULL, attr_y);
196         if (attr) {
197                 if (attr->u.num > ATTR_REL_MAXABS) {
198                         item->rel_y = attr->u.num - ATTR_REL_RELSHIFT;
199                 } else {
200                         item->rel_y = 0;
201                         item->p.y = attr->u.num;
202                 }
203         }
204
205         attr = attr_search(attrs, NULL, attr_font_size);
206         if (attr)
207                 item->font_size = attr->u.num;
208         
209         attr=attr_search(attrs, NULL, attr_background_color);
210         if (attr)
211                 item->color_bg=*attr->u.color;
212         attr = attr_search(attrs, NULL, attr_command);
213         if (attr) 
214                 item->command = g_strdup(attr->u.str);
215         attr=attr_search(attrs, NULL, attr_text_color);
216         if (attr)
217                 item->text_color=*attr->u.color;
218         attr=attr_search(attrs, NULL, attr_flags);
219         if (attr)
220                 item->attr_flags=attr->u.num;
221 }
222
223 void
224 osd_std_config(struct osd_item *item, struct navit *navit)
225 {
226         struct attr attr;
227         dbg(1,"enter\n");
228         if (item->enable_cs) {
229                 item->reconfig_cb = callback_new_1(callback_cast(osd_std_reconfigure), item);
230                 command_saved_set_cb(item->enable_cs, item->reconfig_cb);
231
232                 if (!command_saved_error(item->enable_cs)) {
233                         item->configured = !! command_saved_get_int(item->enable_cs);
234                 } else {
235                         dbg(0, "Error in saved command: %i.\n", command_saved_error(item->enable_cs));
236                 }
237         } else {
238                 if (!navit_get_attr(navit, attr_osd_configuration, &attr, NULL))
239                         attr.u.num=-1;
240                 item->configured = !!(attr.u.num & item->osd_configuration);
241         }
242         graphics_overlay_disable(item->gr, !item->configured);
243 }
244
245 void
246 osd_set_std_graphic(struct navit *nav, struct osd_item *item, struct osd_priv *priv)
247 {
248         struct graphics *navit_gr;
249
250         navit_gr = navit_get_graphics(nav);
251         item->gr = graphics_overlay_new(navit_gr, &item->p, item->w, item->h, 65535, 1);
252
253         item->graphic_bg = graphics_gc_new(item->gr);
254         graphics_gc_set_foreground(item->graphic_bg, &item->color_bg);
255         graphics_background_gc(item->gr, item->graphic_bg);
256
257         item->graphic_fg_white = graphics_gc_new(item->gr);
258         graphics_gc_set_foreground(item->graphic_fg_white, &item->color_white);
259
260         if (item->flags & 2) {
261                 item->font = graphics_font_new(item->gr, item->font_size, 1);
262                 item->graphic_fg_text = graphics_gc_new(item->gr);
263                 graphics_gc_set_foreground(item->graphic_fg_text, &item->text_color);
264         }
265
266         item->cb = callback_new_attr_2(callback_cast(osd_std_config), attr_osd_configuration, item, nav);
267         navit_add_callback(nav, item->cb);
268
269         item->resize_cb = callback_new_attr_2(callback_cast(osd_std_calculate_sizes), attr_resize, item, priv);
270         graphics_add_callback(navit_gr, item->resize_cb);
271
272         osd_std_config(item, nav);
273 }
274
275 void
276 osd_std_draw(struct osd_item *item)
277 {
278         struct point p[2];
279         int flags=item->attr_flags;
280
281         graphics_draw_mode(item->gr, draw_mode_begin);
282         p[0].x=0;
283         p[0].y=0;
284         graphics_draw_rectangle(item->gr, item->graphic_bg, p, item->w, item->h);
285         p[1].x=item->w-1;
286         p[1].y=0;
287         if (flags & 1) 
288                 graphics_draw_lines(item->gr, item->graphic_fg_text, p, 2);
289         p[0].x=item->w-1;
290         p[0].y=item->h-1;
291         if (flags & 2) 
292                 graphics_draw_lines(item->gr, item->graphic_fg_text, p, 2);
293         p[1].x=0;
294         p[1].y=item->h-1;
295         if (flags & 4) 
296                 graphics_draw_lines(item->gr, item->graphic_fg_text, p, 2);
297         p[0].x=0;
298         p[0].y=0;
299         if (flags & 8) 
300                 graphics_draw_lines(item->gr, item->graphic_fg_text, p, 2);
301 }