2 #include <glib/gprintf.h>
8 #include "projection.h"
10 #include "navigation.h"
22 #include "xmlconfig.h"
26 const gchar **attribute_names;
27 const gchar **attribute_values;
28 struct xmlstate *parent;
32 struct element_func *func;
36 static struct attr ** convert_to_attrs(struct xmlstate *state)
38 const gchar **attribute_name=state->attribute_names;
39 const gchar **attribute_value=state->attribute_values;
43 while (*attribute_name) {
47 ret=g_new(struct attr *, count+1);
48 attribute_name=state->attribute_names;
50 while (*attribute_name) {
51 ret[count]=attr_new_from_text(*attribute_name,*attribute_value);
58 dbg(1,"ret=%p\n", ret);
63 static const char * find_attribute(struct xmlstate *state, const char *attribute, int required)
65 const gchar **attribute_name=state->attribute_names;
66 const gchar **attribute_value=state->attribute_values;
67 while(*attribute_name) {
68 if(! g_ascii_strcasecmp(attribute,*attribute_name))
69 return *attribute_value;
74 g_set_error(state->error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, "element '%s' is missing attribute '%s'", state->element, attribute);
79 find_color(struct xmlstate *state, int required, struct color *color)
84 value=find_attribute(state, "color", required);
88 sscanf(value,"#%02x%02x%02x", &r, &g, &b);
89 color->r = (r << 8) | r;
90 color->g = (g << 8) | g;
91 color->b = (b << 8) | b;
93 } else if(strlen(value)==9){
94 sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a);
95 color->r = (r << 8) | r;
96 color->g = (g << 8) | g;
97 color->b = (b << 8) | b;
98 color->a = (a << 8) | a;
100 dbg(0,"color %i has unknown format\n",value);
106 find_order(struct xmlstate *state, int required, int *min, int *max)
108 const char *value, *pos;
113 value=find_attribute(state, "order", required);
116 pos=index(value, '-');
118 ret=sscanf(value,"%d",min);
120 } else if (pos == value)
121 ret=sscanf(value,"-%d",max);
123 ret=sscanf(value,"%d-%d", min, max);
128 find_boolean(struct xmlstate *state, const char *attribute, int deflt, int required)
132 value=find_attribute(state, attribute, required);
135 if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))
141 convert_number(const char *val)
143 return g_ascii_strtoull(val,NULL,0);
147 xmlconfig_plugins(struct xmlstate *state)
149 state->element_object = plugins_new();
150 if (! state->element_object)
156 xmlconfig_plugin(struct xmlstate *state)
161 state->element_object=state->parent->element_object;
162 path=find_attribute(state, "path", 1);
165 active=find_boolean(state, "active", 1, 0);
166 lazy=find_boolean(state, "lazy", 1, 0);
167 plugins_add_path(state->parent->element_object, path, active, lazy);
172 xmlconfig_speech(struct xmlstate *state)
176 type=find_attribute(state, "type", 1);
179 data=find_attribute(state, "data", 0);
180 state->element_object = speech_new(type, data);
181 if (! state->element_object)
183 navit_set_speech(state->parent->element_object, state->element_object);
188 xmlconfig_debug(struct xmlstate *state)
190 const char *name,*level;
191 name=find_attribute(state, "name", 1);
194 level=find_attribute(state, "level", 1);
197 debug_level_set(name, convert_number(level));
202 xmlconfig_navit(struct xmlstate *state)
208 enum projection pro=projection_mg;
210 value=find_attribute(state, "zoom", 0);
212 zoom=convert_number(value);
215 value=find_attribute(state, "center", 0);
216 if (! value || ! coord_parse(value, pro, &co)) {
223 state->element_object = navit_new(&c, zoom);
224 if (! state->element_object)
230 xmlconfig_graphics(struct xmlstate *state)
233 const char *type=find_attribute(state, "type", 1);
236 attrs=convert_to_attrs(state);
237 state->element_object = graphics_new(type, attrs);
238 if (! state->element_object)
240 navit_set_graphics(state->parent->element_object, state->element_object, type);
245 xmlconfig_gui(struct xmlstate *state)
248 const char *type=find_attribute(state, "type", 1);
251 attrs=convert_to_attrs(state);
252 state->element_object = gui_new(state->parent->element_object, type, attrs);
253 if (! state->element_object)
255 navit_set_gui(state->parent->element_object, state->element_object, type);
260 xmlconfig_vehicle(struct xmlstate *state)
262 const char *s=find_attribute(state, "source", 1);
263 const char *value,*name;
265 int update=1, follow=0, active;
266 struct navit_vehicle *nv;
270 if (! find_color(state, 1, &color))
272 state->element_object = vehicle_new(s);
273 if (! state->element_object)
275 if ((value=find_attribute(state, "update", 0)))
276 update=convert_number(value);
277 if ((value=find_attribute(state, "follow", 0)))
278 follow=convert_number(value);
279 active=find_boolean(state, "active", 1, 0);
280 name=find_attribute(state, "name", 0);
281 nv=navit_add_vehicle(state->parent->element_object, state->element_object, name, &color, update, follow);
283 navit_set_vehicle(state->parent->element_object, nv);
288 xmlconfig_log(struct xmlstate *state)
291 attrs=convert_to_attrs(state);
292 state->element_object = log_new(attrs);
293 if (! state->element_object)
295 if (vehicle_add_log(state->parent->element_object, state->element_object, attrs))
302 xmlconfig_window_items(struct xmlstate *state)
305 enum item_type itype;
306 const char *name=find_attribute(state, "name", 1);
307 const char *value=find_attribute(state, "distance", 0);
308 const char *type=find_attribute(state, "type", 1);
309 char *tok,*str,*type_str,*saveptr=NULL;
313 distance=convert_number(value);
314 state->element_object = navit_window_items_new(name, distance);
315 type_str=g_strdup(type);
317 while ((tok=strtok_r(str, ",", &saveptr))) {
318 itype=item_from_name(tok);
319 navit_window_items_add_item(state->element_object, itype);
324 navit_add_window_items(state->parent->element_object, state->element_object);
331 xmlconfig_tracking(struct xmlstate *state)
333 state->element_object = tracking_new(NULL);
334 navit_tracking_add(state->parent->element_object, state->element_object);
339 xmlconfig_route(struct xmlstate *state)
341 state->element_object = route_new(NULL);
342 navit_route_add(state->parent->element_object, state->element_object);
347 xmlconfig_speed(struct xmlstate *state)
352 enum item_type itype;
353 char *saveptr=NULL, *tok, *type_str, *str;
355 type=find_attribute(state, "type", 1);
358 value=find_attribute(state, "value", 1);
361 v=convert_number(value);
362 type_str=g_strdup(type);
364 while ((tok=strtok_r(str, ",", &saveptr))) {
365 itype=item_from_name(tok);
366 route_set_speed(state->parent->element_object, itype, v);
376 xmlconfig_navigation(struct xmlstate *state)
378 state->element_object = navigation_new(NULL);
379 navit_navigation_add(state->parent->element_object, state->element_object);
384 xmlconfig_osd(struct xmlstate *state)
387 const char *type=find_attribute(state, "type", 1);
390 attrs=convert_to_attrs(state);
391 state->element_object = osd_new(state->parent->element_object, type, attrs);
396 xmlconfig_announce(struct xmlstate *state)
398 const char *type,*value;
402 enum item_type itype;
403 char *saveptr=NULL, *tok, *type_str, *str;
405 type=find_attribute(state, "type", 1);
408 for (i = 0 ; i < 3 ; i++) {
409 sprintf(key,"level%d", i);
410 value=find_attribute(state, key, 0);
412 level[i]=convert_number(value);
416 type_str=g_strdup(type);
418 while ((tok=strtok_r(str, ",", &saveptr))) {
419 itype=item_from_name(tok);
420 navigation_set_announce(state->parent->element_object, itype, level);
428 xmlconfig_mapset(struct xmlstate *state)
430 state->element_object = mapset_new();
431 if (! state->element_object)
433 navit_add_mapset(state->parent->element_object, state->element_object);
439 xmlconfig_map(struct xmlstate *state)
442 const char *type=find_attribute(state, "type", 1);
445 attrs=convert_to_attrs(state);
446 state->element_object = map_new(type, attrs);
447 if (! state->element_object)
449 if (!find_boolean(state, "active", 1, 0))
450 map_set_active(state->element_object, 0);
451 mapset_add(state->parent->element_object, state->element_object);
457 xmlconfig_layout(struct xmlstate *state)
459 const char *name=find_attribute(state, "name", 1);
463 state->element_object = layout_new(name);
464 if (! state->element_object)
466 navit_add_layout(state->parent->element_object, state->element_object);
471 xmlconfig_layer(struct xmlstate *state)
473 const char *name=find_attribute(state, "name", 1);
476 state->element_object = layer_new(name, convert_number(find_attribute(state, "details", 0)));
477 if (! state->element_object)
479 layout_add_layer(state->parent->element_object, state->element_object);
484 xmlconfig_item(struct xmlstate *state)
486 const char *type=find_attribute(state, "type", 1);
488 enum item_type itype;
489 char *saveptr=NULL, *tok, *type_str, *str;
493 if (! find_order(state, 1, &min, &max))
495 state->element_object=itemtype_new(min, max);
496 if (! state->element_object)
498 type_str=g_strdup(type);
500 layer_add_itemtype(state->parent->element_object, state->element_object);
501 while ((tok=strtok_r(str, ",", &saveptr))) {
502 itype=item_from_name(tok);
503 itemtype_add_type(state->element_object, itype);
512 xmlconfig_polygon(struct xmlstate *state)
516 if (! find_color(state, 1, &color))
518 state->element_object=polygon_new(&color);
519 if (! state->element_object)
521 itemtype_add_element(state->parent->element_object, state->element_object);
527 xmlconfig_polyline(struct xmlstate *state)
533 if (! find_color(state, 1, &color))
535 width=find_attribute(state, "width", 0);
537 w=convert_number(width);
538 state->element_object=polyline_new(&color, w);
539 if (! state->element_object)
541 itemtype_add_element(state->parent->element_object, state->element_object);
547 xmlconfig_circle(struct xmlstate *state)
550 const char *width, *radius, *label_size;
553 if (! find_color(state, 1, &color))
555 width=find_attribute(state, "width", 0);
557 w=convert_number(width);
558 radius=find_attribute(state, "radius", 0);
560 r=convert_number(radius);
561 label_size=find_attribute(state, "label_size", 0);
563 ls=convert_number(label_size);
564 state->element_object=circle_new(&color, r, w, ls);
565 if (! state->element_object)
567 itemtype_add_element(state->parent->element_object, state->element_object);
573 xmlconfig_label(struct xmlstate *state)
575 const char *label_size;
578 label_size=find_attribute(state, "label_size", 0);
580 ls=convert_number(label_size);
581 state->element_object=label_new(ls);
582 if (! state->element_object)
584 itemtype_add_element(state->parent->element_object, state->element_object);
590 xmlconfig_icon(struct xmlstate *state)
592 const char *src=find_attribute(state, "src", 1);
596 state->element_object=icon_new(src);
597 if (! state->element_object)
599 itemtype_add_element(state->parent->element_object, state->element_object);
605 xmlconfig_image(struct xmlstate *state)
607 state->element_object=image_new();
608 if (! state->element_object)
610 itemtype_add_element(state->parent->element_object, state->element_object);
615 struct element_func {
618 int (*func)(struct xmlstate *state);
620 { "debug", NULL, xmlconfig_debug},
621 { "navit", NULL, xmlconfig_navit},
622 { "graphics", "navit", xmlconfig_graphics},
623 { "gui", "navit", xmlconfig_gui},
624 { "layout", "navit", xmlconfig_layout},
625 { "layer", "layout", xmlconfig_layer},
626 { "item", "layer", xmlconfig_item},
627 { "circle", "item", xmlconfig_circle},
628 { "icon", "item", xmlconfig_icon},
629 { "image", "item", xmlconfig_image},
630 { "label", "item", xmlconfig_label},
631 { "polygon", "item", xmlconfig_polygon},
632 { "polyline", "item", xmlconfig_polyline},
633 { "mapset", "navit", xmlconfig_mapset},
634 { "map", "mapset", xmlconfig_map},
635 { "navigation", "navit", xmlconfig_navigation},
636 { "osd", "navit", xmlconfig_osd},
637 { "announce", "navigation", xmlconfig_announce},
638 { "speech", "navit", xmlconfig_speech},
639 { "tracking", "navit", xmlconfig_tracking},
640 { "route", "navit", xmlconfig_route},
641 { "speed", "route", xmlconfig_speed},
642 { "vehicle", "navit", xmlconfig_vehicle},
643 { "log", "vehicle", xmlconfig_log},
644 { "window_items", "navit", xmlconfig_window_items},
645 { "plugins", NULL, xmlconfig_plugins},
646 { "plugin", "plugins", xmlconfig_plugin},
651 start_element (GMarkupParseContext *context,
652 const gchar *element_name,
653 const gchar **attribute_names,
654 const gchar **attribute_values,
658 struct xmlstate *new=NULL, **parent = user_data;
659 struct element_func *e=elements,*func=NULL;
660 const char *parent_name=NULL;
662 if (!g_ascii_strcasecmp(element_name, e->name)) {
668 g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
669 "Unknown element '%s'", element_name);
673 parent_name=(*parent)->element;
674 if ((parent_name && func->parent && g_ascii_strcasecmp(parent_name, func->parent)) ||
675 (!parent_name && func->parent) || (parent_name && !func->parent)) {
676 g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
677 "Element '%s' within unexpected context '%s'. Expected '%s'",
678 element_name, parent_name, func->parent);
682 new=g_new(struct xmlstate, 1);
683 new->attribute_names=attribute_names;
684 new->attribute_values=attribute_values;
686 new->element_object=NULL;
687 new->element=element_name;
691 if (!find_boolean(new, "enabled", 1, 0))
693 if (new->parent && !new->parent->element_object)
695 if (!func->func(new)) {
700 struct elem_data *data = user_data;
704 parent_object=data->elem_stack ? data->elem_stack->data : NULL;
705 parent_token=data->token_stack ? data->token_stack->data : NULL;
707 /* g_printf("start_element: %s AN: %s AV: %s\n",element_name,*attribute_names,*attribute_values); */
710 printf("Unknown element '%s'\n", element_name);
712 data->elem_stack = g_list_prepend(data->elem_stack, elem);
713 data->token_stack = g_list_prepend(data->token_stack, (gpointer)element_name);
719 /* Called for close tags </foo> */
721 end_element (GMarkupParseContext *context,
722 const gchar *element_name,
726 struct xmlstate *curr, **state = user_data;
729 if(!g_ascii_strcasecmp("plugins", element_name) && curr->element_object)
730 plugins_init(curr->element_object);
731 if(!g_ascii_strcasecmp("navit", element_name) && curr->element_object)
732 navit_init(curr->element_object);
738 /* Called for character data */
739 /* text is not nul-terminated */
741 text (GMarkupParseContext *context,
747 struct xmlstate **state = user_data;
754 static const GMarkupParser parser = {
763 gboolean config_load(char *filename, GError **error)
765 GMarkupParseContext *context;
773 struct xmlstate *curr=NULL;
775 context = g_markup_parse_context_new (&parser, 0, &curr, NULL);
777 if (!g_file_get_contents (filename, &contents, &len, error))
780 result = g_markup_parse_context_parse (context, contents, len, error);
781 if (result && curr) {
782 g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_PARSE, "element '%s' not closed", curr->element);
785 if (!result && error && *error) {
786 g_markup_parse_context_get_position(context, &line, &chr);
787 message=g_strdup_printf("%s at line %d, char %d\n", (*error)->message, line, chr);
788 g_free((*error)->message);
789 (*error)->message=message;
791 g_markup_parse_context_free (context);