X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fdemo-Gtk-conf.c;h=d41b58577c2c524ca8429e8261660c3b70bdc063;hb=488f2fa8fbdbc77e91a70da2962d73af49e6cace;hp=608e488c898e225617434fa03258e1d7a50f2cb2;hpb=6a1da724858673ac40aa13a9612340d8bed8c7b9;p=xscreensaver diff --git a/driver/demo-Gtk-conf.c b/driver/demo-Gtk-conf.c index 608e488c..d41b5857 100644 --- a/driver/demo-Gtk-conf.c +++ b/driver/demo-Gtk-conf.c @@ -1,5 +1,5 @@ /* demo-Gtk-conf.c --- implements the dynamic configuration dialogs. - * xscreensaver, Copyright (c) 2001, 2003 Jamie Zawinski + * xscreensaver, Copyright (c) 2001, 2003, 2004, 2006 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -114,7 +114,6 @@ typedef struct { */ xmlChar *arg_set; /* command-line option to set for "yes", or null */ xmlChar *arg_unset; /* command-line option to set for "no", or null */ - xmlChar *test; /* #### no idea - enablement? */ /* select */ @@ -122,8 +121,6 @@ typedef struct { /* select_option */ - GList *enable; - GtkWidget *widget; } parameter; @@ -150,19 +147,11 @@ free_parameter (parameter *p) if (p->arg) free (p->arg); if (p->arg_set) free (p->arg_set); if (p->arg_unset) free (p->arg_unset); - if (p->test) free (p->test); for (rest = p->options; rest; rest = rest->next) if (rest->data) free_parameter ((parameter *) rest->data); - for (rest = p->enable; rest; rest = rest->next) - { - free ((char *) rest->data); - rest->data = 0; - } - if (p->enable) g_list_free (p->enable); - memset (p, ~0, sizeof(*p)); free (p); } @@ -202,7 +191,6 @@ describe_parameter (FILE *out, parameter *p) if (p->invert_p) fprintf (out, " convert=\"invert\""); if (p->arg_set) fprintf (out, " arg-set=\"%s\"", p->arg_set); if (p->arg_unset) fprintf (out, " arg-unset=\"%s\"", p->arg_unset); - if (p->test) fprintf (out, " test=\"%s\"", p->test); fprintf (out, ">\n"); if (p->type == SELECT) @@ -217,15 +205,6 @@ describe_parameter (FILE *out, parameter *p) if (o->label) fprintf (out, " _label=\"%s\"", o->label); if (o->arg_set) fprintf (out, " arg-set=\"%s\"", o->arg_set); if (o->arg_unset) fprintf (out, " arg-unset=\"%s\"", o->arg_unset); - if (o->test) fprintf (out, " test=\"%s\"", o->test); - if (o->enable) - { - GList *e; - fprintf (out, " enable=\""); - for (e = o->enable; e; e = e->next) - fprintf (out, "%s%s", (char *) e->data, (e->next ? "," : "")); - fprintf (out, "\""); - } fprintf (out, ">\n"); } fprintf (out, "\n"); @@ -264,6 +243,11 @@ xml_get_float (xmlNodePtr node, const xmlChar *name, gboolean *floatpP) static void sanity_check_parameter (const char *filename, const xmlChar *node_name, parameter *p); +static void sanity_check_text_node (const char *filename, + const xmlNodePtr node); +static void sanity_check_menu_options (const char *filename, + const xmlChar *node_name, + parameter *p); /* Allocates and returns a new `parameter' object based on the properties in the given XML node. Returns 0 if there's nothing @@ -293,6 +277,19 @@ make_parameter (const char *filename, xmlNodePtr node) else if (!strcmp (name, "file")) p->type = FILENAME; else if (!strcmp (name, "number")) p->type = SPINBUTTON; else if (!strcmp (name, "select")) p->type = SELECT; + + else if (!strcmp (name, "xscreensaver-text") || /* these are ignored in X11 */ + !strcmp (name, "xscreensaver-image")) /* (they are used in Cocoa) */ + { + free (p); + return 0; + } + else if (node->type == XML_TEXT_NODE) + { + sanity_check_text_node (filename, node); + free (p); + return 0; + } else { if (debug_p) @@ -338,7 +335,6 @@ make_parameter (const char *filename, xmlNodePtr node) p->arg = xmlGetProp (node, (xmlChar *) "arg"); p->arg_set = xmlGetProp (node, (xmlChar *) "arg-set"); p->arg_unset = xmlGetProp (node, (xmlChar *) "arg-unset"); - p->test = xmlGetProp (node, (xmlChar *) "test"); /* Check for missing decimal point */ if (debug_p && @@ -376,6 +372,11 @@ make_select_option (const char *filename, xmlNodePtr node) { if (node->type == XML_COMMENT_NODE) return 0; + else if (node->type == XML_TEXT_NODE) + { + sanity_check_text_node (filename, node); + return 0; + } else if (node->type != XML_ELEMENT_NODE) { if (debug_p) @@ -395,27 +396,12 @@ make_select_option (const char *filename, xmlNodePtr node) else { parameter *s = calloc (1, sizeof(*s)); - char *enable, *e; s->type = SELECT_OPTION; s->id = xmlGetProp (node, (xmlChar *) "id"); s->label = xmlGetProp (node, (xmlChar *) "_label"); s->arg_set = xmlGetProp (node, (xmlChar *) "arg-set"); s->arg_unset = xmlGetProp (node, (xmlChar *) "arg-unset"); - s->test = xmlGetProp (node, (xmlChar *) "test"); - enable = (char*)xmlGetProp (node, (xmlChar *) "enable"); - - if (enable) - { - enable = strdup (enable); - e = strtok (enable, ", "); - while (e) - { - s->enable = g_list_append (s->enable, strdup (e)); - e = strtok (0, ", "); - } - free (enable); - } sanity_check_parameter (filename, node->name, s); return s; @@ -555,9 +541,129 @@ sanity_check_parameter (const char *filename, const xmlChar *node_name, CHECK (arg_unset, "arg-unset"); # undef CHECK # undef WARN + + if (p->type == SELECT) + sanity_check_menu_options (filename, node_name, p); +} + + +static void +sanity_check_menu_options (const char *filename, const xmlChar *node_name, + parameter *p) +{ + GList *opts; + int noptions = 0; + int nulls = 0; + char *prefix = 0; + +/* fprintf (stderr, "\n## %s\n", p->id);*/ + for (opts = p->options; opts; opts = opts->next) + { + parameter *s = (parameter *) opts->data; + if (!s->arg_set) nulls++; + noptions++; + + if (s->arg_set) + { + char *a = strdup ((char *) s->arg_set); + char *spc = strchr (a, ' '); + if (spc) *spc = 0; + if (prefix) + { + if (strcmp (a, prefix)) + fprintf (stderr, + "%s: %s: both \"%s\" and \"%s\" used in \n", + blurb(), filename, p->id); +} + + +/* "text" nodes show up for all the non-tag text in the file, including + all the newlines between tags. Warn if there is text there that + is not whitespace. + */ +static void +sanity_check_text_node (const char *filename, const xmlNodePtr node) +{ + const char *body = (const char *) node->content; + if (node->type != XML_TEXT_NODE) abort(); + while (isspace (*body)) body++; + if (*body) + fprintf (stderr, "%s: WARNING: %s: random text present: \"%s\"\n", + blurb(), filename, body); } +/* Returns a list of strings, every switch mentioned in the parameters. + The strings must be freed. + */ +static GList * +get_all_switches (const char *filename, GList *parms) +{ + GList *switches = 0; + GList *p; + for (p = parms; p; p = p->next) + { + parameter *pp = (parameter *) p->data; + + if (pp->type == SELECT) + { + GList *list2 = get_all_switches (filename, pp->options); + switches = g_list_concat (switches, list2); + } + if (pp->arg && *pp->arg) + switches = g_list_append (switches, strdup ((char *) pp->arg)); + if (pp->arg_set && *pp->arg_set) + switches = g_list_append (switches, strdup ((char *) pp->arg_set)); + if (pp->arg_unset && *pp->arg_unset) + switches = g_list_append (switches, strdup ((char *) pp->arg_unset)); + } + return switches; +} + + +/* Ensures that no switch is mentioned more than once. + */ +static void +sanity_check_parameters (const char *filename, GList *parms) +{ + GList *list = get_all_switches (filename, parms); + GList *p; + for (p = list; p; p = p->next) + { + char *sw = (char *) p->data; + GList *p2; + + if (*sw != '-' && *sw != '+') + fprintf (stderr, "%s: %s: switch does not begin with hyphen \"%s\"\n", + blurb(), filename, sw); + + for (p2 = p->next; p2; p2 = p2->next) + { + const char *sw2 = (const char *) p2->data; + if (!strcmp (sw, sw2)) + fprintf (stderr, "%s: %s: duplicate switch \"%s\"\n", + blurb(), filename, sw); + } + + free (sw); + } + g_list_free (list); +} + /* Helper for make_parameters() */ @@ -618,7 +724,8 @@ make_parameters (const char *filename, xmlNodePtr node, GtkWidget *parent) { if (node->type == XML_ELEMENT_NODE && !strcmp ((char *) node->name, "screensaver")) - return make_parameters_1 (filename, node->xmlChildrenNode, parent, &row); + return make_parameters_1 (filename, node->xmlChildrenNode, + parent, &row); } return 0; } @@ -642,6 +749,7 @@ make_adjustment (const char *filename, parameter *p) : p->value); gfloat si = (p->high - p->low) / 100; gfloat pi = (p->high - p->low) / 10; + gfloat page_size = ((p->type == SLIDER) ? 1 : 0); if (p->value < p->low || p->value > p->high) { @@ -679,8 +787,8 @@ make_adjustment (const char *filename, parameter *p) return GTK_ADJUSTMENT (gtk_adjustment_new (value, p->low, - p->high + 1, - si, pi, 1)); + p->high + page_size, + si, pi, page_size)); } @@ -1194,7 +1302,7 @@ parameter_to_switch (parameter *p) return 0; if (p->integer_p) - sprintf (buf, "%d", (int) (value + 0.5)); + sprintf (buf, "%d", (int) (value + (value > 0 ? 0.5 : -0.5))); else sprintf (buf, "%.4f", value); @@ -1360,7 +1468,7 @@ parse_command_line_into_parameters (const char *filename, char *option = rest->data; rest->data = 0; - if (option[0] != '-') + if (option[0] != '-' && option[0] != '+') { if (debug_p) fprintf (stderr, "%s: WARNING: %s: not a switch: \"%s\"\n", @@ -1433,8 +1541,8 @@ parse_command_line_into_parameters_1 (const char *filename, { GList *p; parameter *match = 0; - int which = -1; - int index = 0; + gint which = -1; + gint index = 0; for (p = parms; p; p = p->next) { @@ -1502,11 +1610,11 @@ parse_command_line_into_parameters_1 (const char *filename, break; case BOOLEAN: if (which != 0 && which != 1) abort(); - parameter_set_switch (match, (gpointer) which); + parameter_set_switch (match, GINT_TO_POINTER(which)); break; case SELECT_OPTION: if (which != 1) abort(); - parameter_set_switch (parent, (gpointer) index); + parameter_set_switch (parent, GINT_TO_POINTER(index)); break; default: break; @@ -1553,13 +1661,13 @@ parameter_set_switch (parameter *p, gpointer value) case BOOLEAN: { GtkToggleButton *b = GTK_TOGGLE_BUTTON (p->widget); - gtk_toggle_button_set_active (b, (int) value); + gtk_toggle_button_set_active (b, GPOINTER_TO_INT(value)); break; } case SELECT: { gtk_option_menu_set_history (GTK_OPTION_MENU (p->widget), - (int) value); + GPOINTER_TO_INT(value)); break; } default: @@ -1642,7 +1750,7 @@ restore_defaults (const char *progname, GList *parms) */ static char * -get_description (GList *parms) +get_description (GList *parms, gboolean verbose_p) { parameter *doc = 0; for (; parms; parms = parms->next) @@ -1661,6 +1769,7 @@ get_description (GList *parms) { char *d = strdup ((char *) doc->string); char *s; + char *p; for (s = d; *s; s++) if (s[0] == '\n') { @@ -1687,7 +1796,27 @@ get_description (GList *parms) d[--L] = 0; } - return _(d); + /* strip off duplicated whitespaces */ + for (s = d; *s; s++) + if (s[0] == ' ') + { + p = s+1; + while (*s == ' ') + s++; + if (*p && (s != p)) + memmove (p, s, strlen(s)+1); + } + +#if 0 + if (verbose_p) + { + fprintf (stderr, "%s: text read is \"%s\"\n", blurb(),doc->string); + fprintf (stderr, "%s: description is \"%s\"\n", blurb(), d); + fprintf (stderr, "%s: translation is \"%s\"\n", blurb(), _(d)); + } +#endif /* 0 */ + + return (d); } } @@ -1700,6 +1829,7 @@ load_configurator_1 (const char *program, const char *arguments, gboolean verbose_p) { const char *dir = hack_configuration_path; + char *base_program; int L = strlen (dir); char *file; char *s; @@ -1708,13 +1838,17 @@ load_configurator_1 (const char *program, const char *arguments, if (L == 0) return 0; - file = (char *) malloc (L + strlen (program) + 10); + base_program = strrchr(program, '/'); + if (base_program) base_program++; + if (!base_program) base_program = (char *) program; + + file = (char *) malloc (L + strlen (base_program) + 10); data = (conf_data *) calloc (1, sizeof(*data)); strcpy (file, dir); if (file[L-1] != '/') file[L++] = '/'; - strcpy (file+L, program); + strcpy (file+L, base_program); for (s = file+L; *s; s++) if (*s == '/' || *s == ' ') @@ -1762,6 +1896,7 @@ load_configurator_1 (const char *program, const char *arguments, gtk_widget_show (table); parms = make_parameters (file, doc->xmlRootNode, table); + sanity_check_parameters (file, parms); xmlFreeDoc (doc); @@ -1771,7 +1906,7 @@ load_configurator_1 (const char *program, const char *arguments, data->widget = table; data->parameters = parms; - data->description = get_description (parms); + data->description = get_description (parms, verbose_p); } else {