/* demo-Gtk-conf.c --- implements the dynamic configuration dialogs.
- * xscreensaver, Copyright (c) 2001, 2003, 2004 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "demo-Gtk-conf.h"
-
+/* Deal with deprecation of direct access to struct fields on the way to GTK3
+ See http://live.gnome.org/GnomeGoals/UseGseal
+ */
+#if GTK_CHECK_VERSION(2,14,0)
+# define GET_PARENT(w) gtk_widget_get_parent (w)
+# define GET_ADJ_VALUE(a) gtk_adjustment_get_value (a)
+# define GET_ADJ_UPPER(a) gtk_adjustment_get_upper (a)
+# define GET_ADJ_LOWER(a) gtk_adjustment_get_lower (a)
+#else
+# define GET_PARENT(w) ((w)->parent)
+# define GET_ADJ_VALUE(a) ((a)->value)
+# define GET_ADJ_UPPER(a) ((a)->upper)
+# define GET_ADJ_LOWER(a) ((a)->lower)
+#endif
+
+
extern const char *blurb (void);
static gboolean debug_p = FALSE;
+#define MIN_SLIDER_WIDTH 150
+#define MIN_SPINBUTTON_WIDTH 48
+#define MIN_LABEL_WIDTH 70
+
+
typedef enum {
COMMAND,
FAKE,
*/
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
*/
/* select_option
*/
- GList *enable;
-
GtkWidget *widget;
} parameter;
static parameter *make_select_option (const char *file, xmlNodePtr);
-static void make_parameter_widget (const char *filename,
- parameter *, GtkWidget *, int *);
+static void make_parameter_widget (const char *filename,
+ parameter *, GtkWidget *);
static void browse_button_cb (GtkButton *button, gpointer user_data);
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);
}
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)
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, "</select>\n");
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
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") || /* ignored in X11; */
+ !strcmp (name, "xscreensaver-image") || /* used in Cocoa. */
+ !strcmp (name, "xscreensaver-updater") ||
+ !strcmp (name, "video"))
+ {
+ 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)
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 &&
{
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)
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;
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 <select id=\"%s\">\n",
+ blurb(), filename, prefix, a, p->id);
+ free (prefix);
+ }
+ prefix = a;
+ }
+
+/* fprintf (stderr, "\n %s\n", s->arg_set);*/
+ }
+
+ if (prefix) free (prefix);
+ prefix = 0;
+ if (nulls > 1)
+ fprintf (stderr,
+ "%s: %s: more than one menu with no arg-set in <select id=\"%s\">\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()
*/
static GList *
-make_parameters_1 (const char *filename, xmlNodePtr node,
- GtkWidget *parent, int *row)
+make_parameters_1 (const char *filename, xmlNodePtr node, GtkWidget *parent)
{
GList *list = 0;
: gtk_vbox_new (FALSE, 0));
GList *list2;
gtk_widget_show (box);
+ gtk_box_pack_start (GTK_BOX (parent), box, FALSE, FALSE, 0);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), box, 0, 3, *row, *row + 1,
- 0, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), box, FALSE, FALSE, 0);
-
- if (row)
- (*row)++;
-
- list2 = make_parameters_1 (filename, node->xmlChildrenNode, box, 0);
+ list2 = make_parameters_1 (filename, node->xmlChildrenNode, box);
if (list2)
list = g_list_concat (list, list2);
}
if (p)
{
list = g_list_append (list, p);
- make_parameter_widget (filename, p, parent, row);
+ make_parameter_widget (filename, p, parent);
}
}
}
static GList *
make_parameters (const char *filename, xmlNodePtr node, GtkWidget *parent)
{
- int row = 0;
for (; node; node = node->next)
{
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);
}
return 0;
}
: 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)
{
return GTK_ADJUSTMENT (gtk_adjustment_new (value,
p->low,
- p->high + 1,
- si, pi, 1));
+ p->high + page_size,
+ si, pi, page_size));
}
+static void
+set_widget_min_width (GtkWidget *w, int width)
+{
+ GtkRequisition req;
+ gtk_widget_size_request (GTK_WIDGET (w), &req);
+ if (req.width < width)
+ gtk_widget_set_size_request (GTK_WIDGET (w), width, -1);
+}
+
+
+/* If we're inside a vbox, we need to put an hbox in it, or labels appear
+ on top instead of to the left, and things stretch to the full width of
+ the window.
+ */
+static GtkWidget *
+insert_fake_hbox (GtkWidget *parent)
+{
+ if (GTK_IS_VBOX (parent))
+ {
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 4);
+ gtk_widget_show (hbox);
+ return hbox;
+ }
+ return parent;
+}
+
+
+static void
+link_atk_label_to_widget(GtkWidget *label, GtkWidget *widget)
+{
+ AtkObject *atk_label = gtk_widget_get_accessible (label);
+ AtkObject *atk_widget = gtk_widget_get_accessible (widget);
+
+ atk_object_add_relationship (atk_label, ATK_RELATION_LABEL_FOR,
+ atk_widget);
+ atk_object_add_relationship (atk_widget, ATK_RELATION_LABELLED_BY,
+ atk_label);
+}
+
/* Given a `parameter' struct, allocates an appropriate GtkWidget for it,
and stores it in `p->widget'.
- `row' is used for keeping track of our position during table layout.
- `parent' must be a GtkTable or a GtkBox.
+ `parent' must be a GtkBox.
*/
static void
-make_parameter_widget (const char *filename,
- parameter *p, GtkWidget *parent, int *row)
+make_parameter_widget (const char *filename, parameter *p, GtkWidget *parent)
{
const char *label = (char *) p->label;
if (p->widget) return;
{
case STRING:
{
+ GtkWidget *entry = gtk_entry_new ();
+ parent = insert_fake_hbox (parent);
if (label)
{
GtkWidget *w = gtk_label_new (_(label));
+ link_atk_label_to_widget (w, entry);
gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
gtk_widget_show (w);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
}
- p->widget = gtk_entry_new ();
+ p->widget = entry;
if (p->string)
gtk_entry_set_text (GTK_ENTRY (p->widget), (char *) p->string);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), p->widget, 1, 3,
- *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
break;
}
case FILENAME:
GtkWidget *L = gtk_label_new (label ? _(label) : "");
GtkWidget *entry = gtk_entry_new ();
GtkWidget *button = gtk_button_new_with_label (_("Browse..."));
+ link_atk_label_to_widget (L, entry);
gtk_widget_show (entry);
gtk_widget_show (button);
p->widget = entry;
gtk_label_set_justify (GTK_LABEL (L), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (L), 1.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (L), MIN_LABEL_WIDTH);
gtk_widget_show (L);
if (p->string)
gtk_entry_set_text (GTK_ENTRY (entry), (char *) p->string);
- if (row)
- {
- gtk_table_attach (GTK_TABLE (parent), L, 0, 1,
- *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (parent), entry, 1, 2,
- *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_table_attach (GTK_TABLE (parent), button, 2, 3,
- *row, *row + 1,
- 0, 0, 0, 0);
- }
- else
- {
- gtk_box_pack_start (GTK_BOX (parent), L, FALSE, FALSE, 4);
- gtk_box_pack_start (GTK_BOX (parent), entry, TRUE, TRUE, 4);
- gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 4);
- }
+ parent = insert_fake_hbox (parent);
+ gtk_box_pack_start (GTK_BOX (parent), L, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), entry, TRUE, TRUE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 4);
break;
}
case SLIDER:
if (label)
{
labelw = gtk_label_new (_(label));
+ link_atk_label_to_widget (labelw, scale);
gtk_label_set_justify (GTK_LABEL (labelw), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (labelw), 0.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (labelw), MIN_LABEL_WIDTH);
gtk_widget_show (labelw);
+ gtk_box_pack_start (GTK_BOX (parent), labelw, FALSE, FALSE, 2);
}
- if (GTK_IS_VBOX (parent))
- {
- /* If we're inside a vbox, we need to put an hbox in it, to get
- the low/high labels to be to the left/right of the slider.
- */
- GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-
- /* But if we have a label, put that above the slider's hbox. */
- if (labelw)
- {
- gtk_box_pack_start (GTK_BOX (parent), labelw, FALSE, TRUE, 2);
- labelw = 0;
- }
-
- gtk_box_pack_start (GTK_BOX (parent), hbox, TRUE, TRUE, 6);
- gtk_widget_show (hbox);
- parent = hbox;
- }
-
- if (labelw)
- {
- if (row)
- {
- gtk_table_attach (GTK_TABLE (parent), labelw,
- 0, 3, *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- (*row)++;
- }
- else
- {
- if (GTK_IS_HBOX (parent))
- {
- GtkWidget *box = gtk_vbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX (parent), box, FALSE, TRUE, 0);
- gtk_widget_show (box);
- gtk_box_pack_start (GTK_BOX (box), labelw, FALSE, TRUE, 4);
- parent = box;
- box = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (box);
- gtk_box_pack_start (GTK_BOX (parent), box, TRUE, TRUE, 0);
- parent = box;
- }
- else
- gtk_box_pack_start (GTK_BOX (parent), labelw,
- FALSE, TRUE, 0);
- }
- }
+ /* Do this after 'labelw' so that it appears above, not to left. */
+ parent = insert_fake_hbox (parent);
if (p->low_label)
{
GtkWidget *w = gtk_label_new (_((char *) p->low_label));
+ link_atk_label_to_widget (w, scale);
gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
gtk_widget_show (w);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
}
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_BOTTOM);
gtk_scale_set_draw_value (GTK_SCALE (scale), debug_p);
gtk_scale_set_digits (GTK_SCALE (scale), (p->integer_p ? 0 : 2));
- if (row)
- gtk_table_attach (GTK_TABLE (parent), scale, 1, 2,
- *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), scale, TRUE, TRUE, 4);
+ set_widget_min_width (GTK_WIDGET (scale), MIN_SLIDER_WIDTH);
+
+ gtk_box_pack_start (GTK_BOX (parent), scale, FALSE, FALSE, 4);
gtk_widget_show (scale);
if (p->high_label)
{
GtkWidget *w = gtk_label_new (_((char *) p->high_label));
+ link_atk_label_to_widget (w, scale);
gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
gtk_widget_show (w);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), w, 2, 3, *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
}
p->widget = scale;
GtkWidget *spin = gtk_spin_button_new (adj, 15, 0);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE);
gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (spin), TRUE);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), adj->value);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), GET_ADJ_VALUE(adj));
+ set_widget_min_width (GTK_WIDGET (spin), MIN_SPINBUTTON_WIDTH);
if (label)
{
GtkWidget *w = gtk_label_new (_(label));
+ link_atk_label_to_widget (w, spin);
gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+ set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
gtk_widget_show (w);
- if (row)
- gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
- GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), w, TRUE, TRUE, 4);
+ parent = insert_fake_hbox (parent);
+ gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
}
gtk_widget_show (spin);
- if (row)
- {
- GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox);
- gtk_table_attach (GTK_TABLE (parent), hbox, 1, 3,
- *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 8, 0);
- gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, FALSE, 0);
- }
- else
- gtk_box_pack_start (GTK_BOX (parent), spin, FALSE, FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (parent), spin, FALSE, FALSE, 4);
p->widget = spin;
break;
case BOOLEAN:
{
p->widget = gtk_check_button_new_with_label (_(label));
- if (row)
- gtk_table_attach (GTK_TABLE (parent), p->widget, 0, 3,
- *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
+ /* Let these stretch -- doesn't hurt.
+ parent = insert_fake_hbox (parent);
+ */
+ gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
break;
}
case SELECT:
GtkWidget *menu = gtk_menu_new ();
GList *opts;
- if (label && row)
- {
- GtkWidget *w = gtk_label_new (_(label));
- gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
- gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
- gtk_widget_show (w);
- gtk_table_attach (GTK_TABLE (parent), w, 0, 3, *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- (*row)++;
- }
-
for (opts = p->options; opts; opts = opts->next)
{
parameter *s = (parameter *) opts->data;
gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
p->widget = opt;
- if (row)
- gtk_table_attach (GTK_TABLE (parent), p->widget, 0, 3,
- *row, *row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- else
- gtk_box_pack_start (GTK_BOX (parent), p->widget, TRUE, TRUE, 4);
+ parent = insert_fake_hbox (parent);
+ gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
break;
}
{
gtk_widget_set_name (p->widget, (char *) p->id);
gtk_widget_show (p->widget);
- if (row)
- (*row)++;
}
}
file_sel_cancel (GtkWidget *button, gpointer user_data)
{
GtkWidget *dialog = button;
- while (dialog->parent)
- dialog = dialog->parent;
+ while (GET_PARENT (dialog))
+ dialog = GET_PARENT (dialog);
gtk_widget_destroy (dialog);
}
GtkWidget *entry = GTK_WIDGET (user_data);
GtkWidget *dialog = button;
const char *path;
- while (dialog->parent)
- dialog = dialog->parent;
+
+ while (GET_PARENT (dialog))
+ dialog = GET_PARENT (dialog);
gtk_widget_hide (dialog);
path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog));
char q = s[0];
if (q != '\'' && q != '\"' && q != '`')
abort();
- memmove (s, s+1, strlen (s)+1);
+ memmove (s, s+1, strlen (s));
while (*s && *s != q)
{
if (*s == '\\')
char buf[255];
char *s1;
float value = (p->invert_p
- ? invert_range (adj->lower, adj->upper, adj->value) - 1
- : adj->value);
+ ? invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj),
+ GET_ADJ_VALUE(adj)) - 1
+ : GET_ADJ_VALUE(adj));
if (value == p->value) /* same as default */
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);
All arguments will be properly quoted.
*/
static char *
-parameters_to_cmd_line (GList *parms)
+parameters_to_cmd_line (GList *parms, gboolean default_p)
{
int L = g_list_length (parms);
int LL = 0;
char **strs = (char **) calloc (sizeof (*parms), L);
char *result;
char *out;
- int i;
+ int i, j;
- for (i = 0; parms; parms = parms->next, i++)
+ for (i = 0, j = 0; parms; parms = parms->next, i++)
{
- char *s = parameter_to_switch ((parameter *) parms->data);
- strs[i] = s;
- LL += (s ? strlen(s) : 0) + 1;
+ parameter *p = (parameter *) parms->data;
+ if (!default_p || p->type == COMMAND)
+ {
+ char *s = parameter_to_switch (p);
+ strs[j++] = s;
+ LL += (s ? strlen(s) : 0) + 1;
+ }
}
result = (char *) malloc (LL + 10);
out = result;
- for (i = 0; i < L; i++)
+ for (i = 0; i < j; i++)
if (strs[i])
{
strcpy (out, strs[i]);
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",
if (1 == sscanf ((char *) value, "%f %c", &f, &c))
{
if (p->invert_p)
- f = invert_range (adj->lower, adj->upper, f) - 1;
+ f = invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj), f) - 1;
gtk_adjustment_set_value (adj, f);
}
break;
s++;
else if (s[1] == ' ' || s[1] == '\t')
s++; /* next line is indented: leave newline */
+ else if (!strncmp(s+1, "http:", 5))
+ s++; /* next line begins a URL: leave newline */
else
s[0] = ' '; /* delete newline to un-fold this line */
}
gboolean verbose_p)
{
const char *dir = hack_configuration_path;
+ char *base_program;
int L = strlen (dir);
char *file;
char *s;
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 == ' ')
char chars[1024];
xmlParserCtxtPtr ctxt;
xmlDocPtr doc = 0;
- GtkWidget *table;
+ GtkWidget *vbox0;
GList *parms;
if (verbose_p)
/* Parsed the XML file. Now make some widgets. */
- table = gtk_table_new (1, 3, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE (table), 4);
- gtk_table_set_col_spacings (GTK_TABLE (table), 4);
- gtk_container_set_border_width (GTK_CONTAINER (table), 8);
- gtk_widget_show (table);
+ vbox0 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox0);
- parms = make_parameters (file, doc->xmlRootNode, table);
+ parms = make_parameters (file, doc->xmlRootNode, vbox0);
+ sanity_check_parameters (file, parms);
xmlFreeDoc (doc);
if (arguments && *arguments)
parse_command_line_into_parameters (program, arguments, parms);
- data->widget = table;
+ data->widget = vbox0;
data->parameters = parms;
data->description = get_description (parms, verbose_p);
}
char *
-get_configurator_command_line (conf_data *data)
+get_configurator_command_line (conf_data *data, gboolean default_p)
{
- char *args = parameters_to_cmd_line (data->parameters);
+ char *args = parameters_to_cmd_line (data->parameters, default_p);
char *result = (char *) malloc (strlen (data->progname) +
strlen (args) + 2);
strcpy (result, data->progname);