/* Xoo - a graphical wrapper around xnest * * Copyright 2004,2005 Matthew Allum, Openedhand Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "config.h" #include #include #include #include #include #include #include #include #include /* dirname() */ #include #include #include "fakedev.h" char * config_load_file (const char *filename) { struct stat st; FILE *fp; char *str; int len; char tmp[1024]; strncpy (tmp, filename, 1024); if (stat (tmp, &st)) { snprintf (tmp, 1024, "%s.xml", filename); if (stat (tmp, &st)) { snprintf (tmp, 1024, PKGDATADIR "/%s", filename); if (stat (tmp, &st)) { snprintf (tmp, 1024, PKGDATADIR "/%s.xml", filename); if (stat (tmp, &st)) return NULL; } } } if (!(fp = fopen (tmp, "rb"))) return NULL; /* Read in the file. */ str = malloc (sizeof (char) * (st.st_size + 1)); len = fread (str, 1, st.st_size, fp); if (len >= 0) str[len] = '\0'; fclose (fp); /* change to the same directory as the conf file - for images */ chdir (dirname (tmp)); return str; } static const char * config_get_val (char *key, const char **attr) { int i = 0; while (attr[i] != NULL) { if (!strcmp (attr[i], key)) return attr[i + 1]; i += 2; } return NULL; } static GdkPixbuf * config_load_image (FakeApp * app, const char *filename) { GError *error = NULL; GdkPixbuf *pixbuf; char tmp[1024]; struct stat st; strncpy (tmp, filename, 1024); if (stat (tmp, &st)) { snprintf (tmp, 1024, PKGDATADIR "/%s", filename); if (stat (tmp, &st)) { return NULL; } } pixbuf = gdk_pixbuf_new_from_file (tmp, &error); if (error == NULL) { return pixbuf; } else { g_warning ("Could not load %s: %s", filename, error->message); g_error_free (error); return NULL; } } static int config_handle_button_tag (FakeApp * app, const char **attr) { const char *s; FakeButton *button; int x, y, width, height; KeySym keysym; int repeat = 1; GdkPixbuf *img = NULL; if ((s = config_get_val ("width", attr)) == NULL) { fprintf (stderr, "Error: 'button' tag missing width param"); return 0; } width = atoi (s); if ((s = config_get_val ("height", attr)) == NULL) { fprintf (stderr, "Error: 'button' tag missing height param"); return 0; } height = atoi (s); if ((s = config_get_val ("x", attr)) == NULL) { fprintf (stderr, "Error: 'button' tag missing x param"); return 0; } x = atoi (s); if ((s = config_get_val ("y", attr)) == NULL) { fprintf (stderr, "Error: 'button' tag missing y param"); return 0; } y = atoi (s); if ((s = config_get_val ("key", attr)) == NULL) { fprintf (stderr, "Error: 'button' tag missing key param"); return 0; } if ((keysym = XStringToKeysym (s)) == NoSymbol) { fprintf (stderr, "Error: Cant find keysym for '%s'", s); return 0; } /* optional attributes */ if ((s = config_get_val ("img", attr)) != NULL) { if ((img = config_load_image (app, s)) == NULL) { fprintf (stderr, "Error: Falied to load '%s' image.", s); } } if (((s = config_get_val ("repeat", attr)) != NULL) && !strcasecmp (s, "off")) repeat = 0; if (app->button_head == NULL) app->button_head = button_new (app, x, y, width, height, keysym, repeat, img); else { for (button = app->button_head; button->next; button = button->next); button->next = button_new (app, x, y, width, height, keysym, repeat, img); } return 1; } static int config_handle_device_tag (FakeApp * app, const char **attr) { /* width, height, display_width, display_height, display_x, displa_y */ const char *s; if ((s = config_get_val ("width", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing width param"); return 0; } app->device_width = atoi (s); if ((s = config_get_val ("height", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing height param"); return 0; } app->device_height = atoi (s); if ((s = config_get_val ("display_width", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing display_width param"); return 0; } app->device_display_width = atoi (s); if ((s = config_get_val ("display_height", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing display_height param"); return 0; } app->device_display_height = atoi (s); if ((s = config_get_val ("display_x", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing display_x param"); return 0; } app->device_display_x = atoi (s); if ((s = config_get_val ("display_y", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing display_x param"); return 0; } app->device_display_y = atoi (s); if ((s = config_get_val ("img", attr)) == NULL) { fprintf (stderr, "Error: 'device' tag missing img param"); return 0; } if ((app->device_img = config_load_image (app, s)) == NULL) { fprintf (stderr, "Error: Falied to load '%s' image.", s); return 0; } return 1; } static void config_xml_start_cb (void *data, const char *tag, const char **attr) { FakeApp *app = (FakeApp *) data; if (!strcmp (tag, "button")) { if (!config_handle_button_tag (app, attr)) { fprintf (stderr, "Giving up.\n"); exit (1); } } else if (!strcmp (tag, "device")) { if (!config_handle_device_tag (app, attr)) { fprintf (stderr, "Giving up.\n"); exit (1); } } } int config_init (FakeApp * app, char *conf_file) { char *data; XML_Parser p; if ((data = config_load_file (conf_file)) == NULL) { fprintf (stderr, "Couldn't find '%s' device config file\n", conf_file); exit (1); } p = XML_ParserCreate (NULL); if (!p) { fprintf (stderr, "Couldn't allocate memory for XML parser\n"); exit (1); } XML_SetElementHandler (p, config_xml_start_cb, NULL); /* XML_SetCharacterDataHandler(p, chars); */ XML_SetUserData (p, (void *) app); if (!XML_Parse (p, data, strlen (data), 1)) { fprintf (stderr, "XML Parse error at line %d:\n%s\n", XML_GetCurrentLineNumber (p), XML_ErrorString (XML_GetErrorCode (p))); exit (1); } return 1; } void config_reinit (FakeApp * app, char *conf_file) { /* Save these so we can figure out if server needs restarting */ /* int prev_device_display_x = app->device_display_x; int prev_device_display_y = app->device_display_y; int prev_device_display_width = app->device_display_width; int prev_device_display_height = app->device_display_height; */ /* XXX TODO: Free up our old structure images etc XXX */ /* Reload UI - hard ? */ }