/* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2002 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2005 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
#ifdef HAVE_GTK /* whole file */
+#include <xscreensaver-intl.h>
+
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+# ifdef __GNUC__
+# define STFU __extension__ /* ignore gcc -pendantic warnings in next sexp */
+# else
+# define STFU /* */
+# endif
+
+
+#ifdef ENABLE_NLS
+# include <locale.h>
+#endif /* ENABLE_NLS */
+
#ifndef VMS
# include <pwd.h> /* for getpwuid() */
#else /* VMS */
#endif /* HAVE_UNAME */
#include <stdio.h>
+#include <time.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <signal.h>
#include <gdk/gdkx.h>
+#ifdef HAVE_GTK2
+# include <glade/glade-xml.h>
+# include <gmodule.h>
+#else /* !HAVE_GTK2 */
+# define G_MODULE_EXPORT /**/
+#endif /* !HAVE_GTK2 */
+
+#if defined(DEFAULT_ICONDIR) && !defined(GLADE_DIR)
+# define GLADE_DIR DEFAULT_ICONDIR
+#endif
+#if !defined(DEFAULT_ICONDIR) && defined(GLADE_DIR)
+# define DEFAULT_ICONDIR GLADE_DIR
+#endif
+
+#ifndef HAVE_XML
+ /* Kludge: this is defined in demo-Gtk-conf.c when HAVE_XML.
+ It is unused otherwise, so in that case, stub it out. */
+ static const char *hack_configuration_path = 0;
+#endif
+
+
+
#include "version.h"
#include "prefs.h"
#include "resources.h" /* for parse_time() */
#include "logo-50.xpm"
#include "logo-180.xpm"
+#undef dgettext /* else these are defined twice... */
+#undef dcgettext
+
#include "demo-Gtk-widgets.h"
#include "demo-Gtk-support.h"
#include "demo-Gtk-conf.h"
#include <string.h>
#include <ctype.h>
+#ifdef HAVE_GTK2
+enum {
+ COL_ENABLED,
+ COL_NAME,
+ COL_LAST
+};
+#endif /* HAVE_GTK2 */
+
+/* from exec.c */
+extern void exec_command (const char *shell, const char *command, int nice);
+
+static void hack_subproc_environment (Window preview_window_id, Bool debug_p);
+
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
GtkWidget *popup_widget; /* the "Settings" dialog */
conf_data *cdata; /* private data for per-hack configuration */
+#ifdef HAVE_GTK2
+ GladeXML *glade_ui; /* Glade UI file */
+#endif /* HAVE_GTK2 */
+
Bool debug_p; /* whether to print diagnostics */
Bool initializing_p; /* flag for breaking recursion loops */
Bool saving_p; /* flag for breaking recursion loops */
int subproc_timer_id; /* timer to delay subproc launch */
int subproc_check_timer_id; /* timer to check whether it started up */
int subproc_check_countdown; /* how many more checks left */
- int preview_nice_level;
int *list_elt_to_hack_number; /* table for sorting the hack list */
int *hack_number_to_list_elt; /* the inverse table */
+ Bool *hacks_available_p; /* whether hacks are on $PATH */
+ int list_count; /* how many items are in the list: this may be
+ less than p->screenhacks_count, if some are
+ suppressed. */
int _selected_list_element; /* don't use this: call
selected_list_element() instead */
static void await_xscreensaver (state *);
static void schedule_preview (state *, const char *cmd);
-static void kill_preview_subproc (state *);
+static void kill_preview_subproc (state *, Bool reset_p);
static void schedule_preview_check (state *);
if (!name) abort();
if (!*name) abort();
+#ifdef HAVE_GTK2
+ if (!s->glade_ui)
+ {
+ /* First try to load the Glade file from the current directory;
+ if there isn't one there, check the installed directory.
+ */
+# define GLADE_FILE_NAME "xscreensaver-demo.glade2"
+ const char * const files[] = { GLADE_FILE_NAME,
+ GLADE_DIR "/" GLADE_FILE_NAME };
+ int i;
+ for (i = 0; i < countof (files); i++)
+ {
+ struct stat st;
+ if (!stat (files[i], &st))
+ {
+ s->glade_ui = glade_xml_new (files[i], NULL, NULL);
+ break;
+ }
+ }
+ if (!s->glade_ui)
+ {
+ fprintf (stderr,
+ "%s: could not load \"" GLADE_FILE_NAME "\"\n"
+ "\tfrom " GLADE_DIR "/ or current directory.\n",
+ blurb());
+ exit (-1);
+ }
+# undef GLADE_FILE_NAME
+
+ glade_xml_signal_autoconnect (s->glade_ui);
+ }
+
+ w = glade_xml_get_widget (s->glade_ui, name);
+
+#else /* !HAVE_GTK2 */
+
w = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (s->base_widget),
name);
if (w) return w;
w = (GtkWidget *) gtk_object_get_data (GTK_OBJECT (s->popup_widget),
name);
+#endif /* HAVE_GTK2 */
if (w) return w;
fprintf (stderr, "%s: no widget \"%s\"\n", blurb(), name);
static void
ensure_selected_item_visible (GtkWidget *widget)
{
+#ifdef HAVE_GTK2
+ GtkTreePath *path;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ path = gtk_tree_path_new_first ();
+ else
+ path = gtk_tree_model_get_path (model, &iter);
+
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE);
+
+ gtk_tree_path_free (path);
+
+#else /* !HAVE_GTK2 */
+
GtkScrolledWindow *scroller = 0;
GtkViewport *vp = 0;
GtkList *list_widget = 0;
gtk_adjustment_set_value (adj, target);
}
+#endif /* !HAVE_GTK2 */
}
static void
while (parent && !parent->window)
parent = parent->parent;
- if (!GTK_WIDGET (parent)->window) /* too early to pop up transient dialogs */
+ if (!parent ||
+ !GTK_WIDGET (parent)->window) /* too early to pop up transient dialogs */
{
fprintf (stderr, "%s: too early for dialog?\n", progname);
return;
{
label = gtk_label_new (head);
+#ifdef HAVE_GTK2
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+#endif /* HAVE_GTK2 */
+#ifndef HAVE_GTK2
if (i == 1)
{
GTK_WIDGET (label)->style =
gtk_widget_set_style (GTK_WIDGET (label),
GTK_WIDGET (label)->style);
}
-
+#endif /* !HAVE_GTK2 */
if (center <= 0)
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
label, TRUE, TRUE, 0);
+#ifdef HAVE_GTK2
+ if (restart_button_p)
+ {
+ cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+ gtk_container_add (GTK_CONTAINER (label), cancel);
+ }
+
+ ok = gtk_button_new_from_stock (GTK_STOCK_OK);
+ gtk_container_add (GTK_CONTAINER (label), ok);
+
+#else /* !HAVE_GTK2 */
+
ok = gtk_button_new_with_label ("OK");
gtk_container_add (GTK_CONTAINER (label), ok);
gtk_container_add (GTK_CONTAINER (label), cancel);
}
+#endif /* !HAVE_GTK2 */
+
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
gtk_window_set_title (GTK_WINDOW (dialog), progclass);
+ STFU GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
gtk_widget_show (ok);
+ gtk_widget_grab_focus (ok);
+
if (cancel)
- gtk_widget_show (cancel);
+ {
+ STFU GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
+ gtk_widget_show (cancel);
+ }
gtk_widget_show (label);
gtk_widget_show (dialog);
-/* gtk_window_set_default (GTK_WINDOW (dialog), ok);*/
if (restart_button_p)
{
gdk_window_set_transient_for (GTK_WIDGET (dialog)->window,
GTK_WIDGET (parent)->window);
+#ifdef HAVE_GTK2
+ gtk_window_present (GTK_WINDOW (dialog));
+#else /* !HAVE_GTK2 */
gdk_window_show (GTK_WIDGET (dialog)->window);
gdk_window_raise (GTK_WIDGET (dialog)->window);
+#endif /* !HAVE_GTK2 */
free (msg);
}
flush_dialog_changes_and_save (s);
status = xscreensaver_command (GDK_DISPLAY(), command, arg, False, &err);
+
+ /* Kludge: ignore the spurious "window unexpectedly deleted" errors... */
+ if (status < 0 && err && strstr (err, "unexpectedly deleted"))
+ status = 0;
+
if (status < 0)
{
char buf [255];
\f
/* Button callbacks
+
+ According to Eric Lassauge, this G_MODULE_EXPORT crud is needed to make
+ libglade work on Cygwin; apparently all Glade callbacks need this magic
+ extra declaration. I do not pretend to understand.
*/
-void
+G_MODULE_EXPORT void
exit_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
flush_dialog_changes_and_save (s);
- kill_preview_subproc (s);
+ kill_preview_subproc (s, False);
gtk_main_quit ();
}
-static void
+static gboolean
wm_toplevel_close_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
state *s = (state *) data;
flush_dialog_changes_and_save (s);
gtk_main_quit ();
+ return TRUE;
}
-void
+G_MODULE_EXPORT void
about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
char msg [2048];
char *vers = strdup (screensaver_id + 4);
char *s;
char copy[1024];
- char *desc = "For updates, check http://www.jwz.org/xscreensaver/";
+ char *desc = _("For updates, check http://www.jwz.org/xscreensaver/");
s = strchr (vers, ',');
*s = 0;
s += 2;
- sprintf(copy, "Copyright \251 1991-2002 %s", s);
+ /* Ole Laursen <olau@hardworking.dk> says "don't use _() here because
+ non-ASCII characters aren't allowed in localizable string keys."
+ (I don't want to just use (c) instead of © because that doesn't
+ look as good in the plain-old default Latin1 "C" locale.)
+ */
+#ifdef HAVE_GTK2
+ sprintf(copy, ("Copyright \xC2\xA9 1991-2005 %s"), s);
+#else /* !HAVE_GTK2 */
+ sprintf(copy, ("Copyright \251 1991-2005 %s"), s);
+#endif /* !HAVE_GTK2 */
sprintf (msg, "%s\n\n%s", copy, desc);
gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (label1), 0.0, 0.75);
+#ifndef HAVE_GTK2
GTK_WIDGET (label1)->style = gtk_style_copy (GTK_WIDGET (label1)->style);
GTK_WIDGET (label1)->style->font =
gdk_font_load (get_string_resource ("about.headingFont","Dialog.Font"));
gtk_widget_set_style (GTK_WIDGET (label1), GTK_WIDGET (label1)->style);
+#endif /* HAVE_GTK2 */
label2 = gtk_label_new (msg);
gtk_box_pack_start (GTK_BOX (vbox), label2, TRUE, TRUE, 0);
gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (label2), 0.0, 0.25);
+#ifndef HAVE_GTK2
GTK_WIDGET (label2)->style = gtk_style_copy (GTK_WIDGET (label2)->style);
GTK_WIDGET (label2)->style->font =
gdk_font_load (get_string_resource ("about.bodyFont","Dialog.Font"));
gtk_widget_set_style (GTK_WIDGET (label2), GTK_WIDGET (label2)->style);
+#endif /* HAVE_GTK2 */
hb = gtk_hbutton_box_new ();
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
hb, TRUE, TRUE, 0);
- ok = gtk_button_new_with_label ("OK");
+#ifdef HAVE_GTK2
+ ok = gtk_button_new_from_stock (GTK_STOCK_OK);
+#else /* !HAVE_GTK2 */
+ ok = gtk_button_new_with_label (_("OK"));
+#endif /* !HAVE_GTK2 */
gtk_container_add (GTK_CONTAINER (hb), ok);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
}
-void
+G_MODULE_EXPORT void
doc_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
if (!p->help_url || !*p->help_url)
{
warning_dialog (s->toplevel_widget,
- "Error:\n\n"
- "No Help URL has been specified.\n", False, 100);
+ _("Error:\n\n"
+ "No Help URL has been specified.\n"), False, 100);
return;
}
help_command = (char *) malloc (strlen (p->load_url_command) +
- (strlen (p->help_url) * 2) + 20);
+ (strlen (p->help_url) * 4) + 20);
strcpy (help_command, "( ");
sprintf (help_command + strlen(help_command),
- p->load_url_command, p->help_url, p->help_url);
+ p->load_url_command,
+ p->help_url, p->help_url, p->help_url, p->help_url);
strcat (help_command, " ) &");
system (help_command);
free (help_command);
}
-void
+G_MODULE_EXPORT void
activate_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
-void
+G_MODULE_EXPORT void
lock_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
-void
+G_MODULE_EXPORT void
kill_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
-void
+G_MODULE_EXPORT void
restart_menu_cb (GtkWidget *widget, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
Bool root_p = (geteuid () == 0);
strcpy (buf,
- "Error:\n\n"
- "The xscreensaver daemon did not start up properly.\n"
- "\n");
+ _("Error:\n\n"
+ "The xscreensaver daemon did not start up properly.\n"
+ "\n"));
if (root_p)
+
+# ifdef __GNUC__
+ __extension__ /* don't warn about "string length is greater than
+ the length ISO C89 compilers are required to
+ support" in the following expression... */
+# endif
strcat (buf,
- "You are running as root. This usually means that xscreensaver\n"
+ _("You are running as root. This usually means that xscreensaver\n"
"was unable to contact your X server because access control is\n"
"turned on. Try running this command:\n"
"\n"
"manual and FAQ for more information.\n"
"\n"
"You shouldn't run X as root. Instead, you should log in as a\n"
- "normal user, and `su' as necessary.");
+ "normal user, and `su' as necessary."));
else
- strcat (buf, "Please check your $PATH and permissions.");
+ strcat (buf, _("Please check your $PATH and permissions."));
warning_dialog (s->toplevel_widget, buf, False, 1);
}
const char *f = init_file_name();
if (!f || !*f)
warning_dialog (s->toplevel_widget,
- "Error:\n\nCouldn't determine init file name!\n",
+ _("Error:\n\nCouldn't determine init file name!\n"),
False, 100);
else
{
char *b = (char *) malloc (strlen(f) + 1024);
- sprintf (b, "Error:\n\nCouldn't write %s\n", f);
+ sprintf (b, _("Error:\n\nCouldn't write %s\n"), f);
warning_dialog (s->toplevel_widget, b, False, 100);
free (b);
}
}
-void
+G_MODULE_EXPORT void
run_this_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
-void
+G_MODULE_EXPORT void
manual_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
saver_preferences *p = &s->prefs;
- GtkList *list_widget = GTK_LIST (name_to_widget (s, "list"));
+ GtkWidget *list_widget = name_to_widget (s, "list");
int list_elt = selected_list_element (s);
int hack_number;
char *name, *name2, *cmd, *str;
hack_number = s->list_elt_to_hack_number[list_elt];
flush_dialog_changes_and_save (s);
- ensure_selected_item_visible (GTK_WIDGET (list_widget));
+ ensure_selected_item_visible (list_widget);
name = strdup (p->screenhacks[hack_number]->command);
name2 = name;
cmd = get_string_resource ("manualCommand", "ManualCommand");
if (cmd)
{
- char *cmd2 = (char *) malloc (strlen (cmd) + strlen (name2) + 100);
+ char *cmd2 = (char *) malloc (strlen (cmd) + (strlen (name2) * 4) + 100);
strcpy (cmd2, "( ");
sprintf (cmd2 + strlen (cmd2),
cmd,
else
{
warning_dialog (GTK_WIDGET (button),
- "Error:\n\nno `manualCommand' resource set.",
+ _("Error:\n\nno `manualCommand' resource set."),
False, 100);
}
static void
-force_list_select_item (state *s, GtkList *list, int list_elt, Bool scroll_p)
+force_list_select_item (state *s, GtkWidget *list, int list_elt, Bool scroll_p)
{
GtkWidget *parent = name_to_widget (s, "scroller");
Bool was = GTK_WIDGET_IS_SENSITIVE (parent);
+#ifdef HAVE_GTK2
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+#endif /* HAVE_GTK2 */
if (!was) gtk_widget_set_sensitive (parent, True);
+#ifdef HAVE_GTK2
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
+ STFU g_assert (model);
+ gtk_tree_model_iter_nth_child (model, &iter, NULL, list_elt);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+ gtk_tree_selection_select_iter (selection, &iter);
+#else /* !HAVE_GTK2 */
gtk_list_select_item (GTK_LIST (list), list_elt);
+#endif /* !HAVE_GTK2 */
if (scroll_p) ensure_selected_item_visible (GTK_WIDGET (list));
if (!was) gtk_widget_set_sensitive (parent, False);
}
-void
+G_MODULE_EXPORT void
run_next_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
- saver_preferences *p = &s->prefs;
+ /* saver_preferences *p = &s->prefs; */
Bool ops = s->preview_suppressed_p;
- GtkList *list_widget =
- GTK_LIST (name_to_widget (s, "list"));
+ GtkWidget *list_widget = name_to_widget (s, "list");
int list_elt = selected_list_element (s);
if (list_elt < 0)
else
list_elt++;
- if (list_elt >= p->screenhacks_count)
+ if (list_elt >= s->list_count)
list_elt = 0;
s->preview_suppressed_p = True;
flush_dialog_changes_and_save (s);
- force_list_select_item (s, GTK_LIST (list_widget), list_elt, True);
+ force_list_select_item (s, list_widget, list_elt, True);
populate_demo_window (s, list_elt);
run_hack (s, list_elt, False);
}
-void
+G_MODULE_EXPORT void
run_prev_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
- saver_preferences *p = &s->prefs;
+ /* saver_preferences *p = &s->prefs; */
Bool ops = s->preview_suppressed_p;
- GtkList *list_widget =
- GTK_LIST (name_to_widget (s, "list"));
+ GtkWidget *list_widget = name_to_widget (s, "list");
int list_elt = selected_list_element (s);
if (list_elt < 0)
- list_elt = p->screenhacks_count - 1;
+ list_elt = s->list_count - 1;
else
list_elt--;
if (list_elt < 0)
- list_elt = p->screenhacks_count - 1;
+ list_elt = s->list_count - 1;
s->preview_suppressed_p = True;
flush_dialog_changes_and_save (s);
- force_list_select_item (s, GTK_LIST (list_widget), list_elt, True);
+ force_list_select_item (s, list_widget, list_elt, True);
populate_demo_window (s, list_elt);
run_hack (s, list_elt, False);
Bool changed = False;
screenhack *hack;
int hack_number;
- if (list_elt < 0 || list_elt >= p->screenhacks_count)
+ if (list_elt < 0 || list_elt >= s->list_count)
abort();
hack_number = s->list_elt_to_hack_number[list_elt];
else
{
char c;
- if (sscanf (line, "%u%c", &value, &c) != 1)
+ if (sscanf (line, "%d%c", &value, &c) != 1)
value = -1;
if (!sec_p)
value *= 60;
{
char b[255];
sprintf (b,
- "Error:\n\n"
- "Unparsable time format: \"%s\"\n",
+ _("Error:\n\n"
+ "Unparsable time format: \"%s\"\n"),
line);
warning_dialog (s->toplevel_widget, b, False, 100);
}
{
int L;
char *p2, *s;
- if (!path) return 0;
- L = strlen (path);;
+ if (!path || !*path) return 0;
+ L = strlen (path);
p2 = (char *) malloc (L + 2);
strcpy (p2, path);
if (p2[L-1] == '/') /* remove trailing slash */
}
+#ifdef HAVE_GTK2
+
+typedef struct {
+ state *s;
+ int i;
+ Bool *changed;
+} FlushForeachClosure;
+
+static gboolean
+flush_checkbox (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ FlushForeachClosure *closure = data;
+ gboolean checked;
+
+ gtk_tree_model_get (model, iter,
+ COL_ENABLED, &checked,
+ -1);
+
+ if (flush_changes (closure->s, closure->i,
+ checked, 0, 0))
+ *closure->changed = True;
+
+ closure->i++;
+
+ /* don't remove row */
+ return FALSE;
+}
+
+#endif /* HAVE_GTK2 */
+
/* Flush out any changes made in the main dialog window (where changes
take place immediately: clicking on a checkbox causes the init file
to be written right away.)
{
saver_preferences *p = &s->prefs;
saver_preferences P2, *p2 = &P2;
+#ifdef HAVE_GTK2
+ GtkTreeView *list_widget = GTK_TREE_VIEW (name_to_widget (s, "list"));
+ GtkTreeModel *model = gtk_tree_view_get_model (list_widget);
+ FlushForeachClosure closure;
+#else /* !HAVE_GTK2 */
GtkList *list_widget = GTK_LIST (name_to_widget (s, "list"));
GList *kids = gtk_container_children (GTK_CONTAINER (list_widget));
+ int i;
+#endif /* !HAVE_GTK2 */
+
Bool changed = False;
GtkWidget *w;
- int i;
if (s->saving_p) return False;
s->saving_p = True;
/* Flush any checkbox changes in the list down into the prefs struct.
*/
+#ifdef HAVE_GTK2
+ closure.s = s;
+ closure.changed = &changed;
+ closure.i = 0;
+ gtk_tree_model_foreach (model, flush_checkbox, &closure);
+
+#else /* !HAVE_GTK2 */
+
for (i = 0; kids; kids = kids->next, i++)
{
GtkWidget *line = GTK_WIDGET (kids->data);
if (flush_changes (s, i, (checked ? 1 : 0), 0, 0))
changed = True;
}
-
+#endif /* ~HAVE_GTK2 */
/* Flush the non-hack-specific settings down into the prefs struct.
*/
if (p->field != p2->field) { \
changed = True; \
if (s->debug_p) \
- fprintf (stderr, "%s: %s => %d\n", blurb(), name, p2->field); \
+ fprintf (stderr, "%s: %s => %d\n", blurb(), name, (int) p2->field); \
} \
p->field = p2->field
else if (!strcasecmp (visual, "greyscale")) visual = "GrayScale";
else if (!strcasecmp (visual, "pseudocolor")) visual = "PseudoColor";
else if (!strcasecmp (visual, "directcolor")) visual = "DirectColor";
- else if (1 == sscanf (visual, " %ld %c", &id, &c)) ;
+ else if (1 == sscanf (visual, " %lu %c", &id, &c)) ;
else if (1 == sscanf (visual, " 0x%lx %c", &id, &c)) ;
else
{
gdk_beep (); /* unparsable */
visual = "";
- gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry), "Any");
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (vis)->entry), _("Any"));
}
changed = flush_changes (s, list_elt, -1, command, visual);
}
-
-
-void
+G_MODULE_EXPORT void
pref_changed_cb (GtkWidget *widget, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
}
+G_MODULE_EXPORT gboolean
+pref_changed_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ pref_changed_cb (widget, user_data);
+ return FALSE;
+}
/* Callback on menu items in the "mode" options menu.
*/
{
state *s = (state *) user_data;
saver_preferences *p = &s->prefs;
- GtkList *list = GTK_LIST (name_to_widget (s, "list"));
+ GtkWidget *list = name_to_widget (s, "list");
int list_elt;
GList *menu_items = gtk_container_children (GTK_CONTAINER (widget->parent));
int menu_index = 0;
saver_mode new_mode;
- int old_selected = p->selected_hack;
while (menu_items)
{
new_mode = mode_menu_order[menu_index];
/* Keep the same list element displayed as before; except if we're
- switching *to* "one screensaver" mode from any other mode, scroll
- to and select "the one".
+ switching *to* "one screensaver" mode from any other mode, set
+ "the one" to be that which is currently selected.
*/
- list_elt = -1;
+ list_elt = selected_list_element (s);
if (new_mode == ONE_HACK)
- list_elt = (p->selected_hack >= 0
- ? s->hack_number_to_list_elt[p->selected_hack]
- : -1);
-
- if (list_elt < 0)
- list_elt = selected_list_element (s);
+ p->selected_hack = s->list_elt_to_hack_number[list_elt];
{
saver_mode old_mode = p->mode;
}
pref_changed_cb (widget, user_data);
-
- if (old_selected != p->selected_hack)
- abort(); /* dammit, not again... */
}
-void
+G_MODULE_EXPORT void
switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page,
gint page_num, gpointer user_data)
{
schedule_preview (s, 0);
}
+#ifdef HAVE_GTK2
+static void
+list_activated_cb (GtkTreeView *list,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer data)
+{
+ state *s = data;
+ char *str;
+ int list_elt;
+
+ STFU g_return_if_fail (!gdk_pointer_is_grabbed ());
+
+ str = gtk_tree_path_to_string (path);
+ list_elt = strtol (str, NULL, 10);
+ g_free (str);
+
+ if (list_elt >= 0)
+ run_hack (s, list_elt, True);
+}
+
+static void
+list_select_changed_cb (GtkTreeSelection *selection, gpointer data)
+{
+ state *s = (state *)data;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ char *str;
+ int list_elt;
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+
+ path = gtk_tree_model_get_path (model, &iter);
+ str = gtk_tree_path_to_string (path);
+ list_elt = strtol (str, NULL, 10);
+
+ gtk_tree_path_free (path);
+ g_free (str);
+
+ populate_demo_window (s, list_elt);
+ flush_dialog_changes_and_save (s);
+}
+
+#else /* !HAVE_GTK2 */
static time_t last_doubleclick_time = 0; /* FMH! This is to suppress the
list_select_cb that comes in
flush_dialog_changes_and_save (s);
}
+#endif /* !HAVE_GTK2 */
+
/* Called when the checkboxes that are in the left column of the
scrolling list are clicked. This both populates the right pane
also syncs this checkbox with the right pane Enabled checkbox.
*/
static void
-list_checkbox_cb (GtkWidget *cb, gpointer data)
+list_checkbox_cb (
+#ifdef HAVE_GTK2
+ GtkCellRendererToggle *toggle,
+ gchar *path_string,
+#else /* !HAVE_GTK2 */
+ GtkWidget *cb,
+#endif /* !HAVE_GTK2 */
+ gpointer data)
{
state *s = (state *) data;
+#ifdef HAVE_GTK2
+ GtkScrolledWindow *scroller =
+ GTK_SCROLLED_WINDOW (name_to_widget (s, "scroller"));
+ GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list"));
+ GtkTreeModel *model = gtk_tree_view_get_model (list);
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
+ GtkTreeIter iter;
+ gboolean active;
+#else /* !HAVE_GTK2 */
GtkWidget *line_hbox = GTK_WIDGET (cb)->parent;
GtkWidget *line = GTK_WIDGET (line_hbox)->parent;
GtkList *list = GTK_LIST (GTK_WIDGET (line)->parent);
GtkViewport *vp = GTK_VIEWPORT (GTK_WIDGET (list)->parent);
GtkScrolledWindow *scroller = GTK_SCROLLED_WINDOW (GTK_WIDGET (vp)->parent);
+#endif /* !HAVE_GTK2 */
GtkAdjustment *adj;
double scroll_top;
- int list_elt = gtk_list_child_position (list, line);
+ int list_elt;
+
+#ifdef HAVE_GTK2
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ {
+ g_warning ("bad path: %s", path_string);
+ return;
+ }
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (model, &iter,
+ COL_ENABLED, &active,
+ -1);
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ COL_ENABLED, !active,
+ -1);
+
+ list_elt = strtol (path_string, NULL, 10);
+#else /* !HAVE_GTK2 */
+ list_elt = gtk_list_child_position (list, line);
+#endif /* !HAVE_GTK2 */
/* remember previous scroll position of the top of the list */
adj = gtk_scrolled_window_get_vadjustment (scroller);
scroll_top = adj->value;
flush_dialog_changes_and_save (s);
- force_list_select_item (s, list, list_elt, False);
+ force_list_select_item (s, GTK_WIDGET (list), list_elt, False);
populate_demo_window (s, list_elt);
/* restore the previous scroll position of the top of the list.
GtkFileSelection *selector = fsd->widget;
GtkWidget *top = s->toplevel_widget;
saver_preferences *p = &s->prefs;
- char *path = gtk_file_selection_get_filename (selector);
+ const char *path = gtk_file_selection_get_filename (selector);
if (p->image_directory && !strcmp(p->image_directory, path))
return; /* no change */
if (!directory_p (path))
{
char b[255];
- sprintf (b, "Error:\n\n" "Directory does not exist: \"%s\"\n", path);
+ sprintf (b, _("Error:\n\n" "Directory does not exist: \"%s\"\n"), path);
warning_dialog (GTK_WIDGET (top), b, False, 100);
return;
}
}
-void
+G_MODULE_EXPORT void
browse_image_dir_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
}
-void
+G_MODULE_EXPORT void
settings_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
# endif /* HAVE_XML */
}
-void
+G_MODULE_EXPORT void
settings_adv_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
gtk_notebook_set_page (notebook, 1);
}
-void
+G_MODULE_EXPORT void
settings_std_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
gtk_notebook_set_page (notebook, 0);
}
-void
+G_MODULE_EXPORT void
settings_switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page,
gint page_num, gpointer user_data)
{
-void
+G_MODULE_EXPORT void
settings_cancel_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
gtk_widget_hide (s->popup_widget);
}
-void
+G_MODULE_EXPORT void
settings_ok_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
gtk_widget_hide (s->popup_widget);
}
-static void
+static gboolean
wm_popup_close_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
state *s = (state *) data;
settings_cancel_cb (0, (gpointer) s);
+ return TRUE;
}
Atom type;
int format;
unsigned long nitems, bytesafter;
- CARD32 *data = 0;
+ unsigned char *dataP = 0;
Display *dpy = GDK_DISPLAY();
int hack_number = -1;
XA_SCREENSAVER_STATUS,
0, 3, False, XA_INTEGER,
&type, &format, &nitems, &bytesafter,
- (unsigned char **) &data)
+ &dataP)
== Success
&& type == XA_INTEGER
&& nitems >= 3
- && data)
- hack_number = (int) data[2] - 1;
+ && dataP)
+ {
+ CARD32 *data = (CARD32 *) dataP;
+ hack_number = (int) data[2] - 1;
+ }
- if (data) free (data);
+ if (dataP) XFree (dataP);
return hack_number;
}
if (hack_number >= 0 && hack_number < p->screenhacks_count)
{
int list_elt = s->hack_number_to_list_elt[hack_number];
- GtkList *list = GTK_LIST (name_to_widget (s, "list"));
+ GtkWidget *list = name_to_widget (s, "list");
force_list_select_item (s, list, list_elt, True);
populate_demo_window (s, list_elt);
}
}
+static Bool
+on_path_p (const char *program)
+{
+ int result = False;
+ struct stat st;
+ char *cmd = strdup (program);
+ char *token = strchr (cmd, ' ');
+ char *path = 0;
+ int L;
+
+ if (token) *token = 0;
+ token = 0;
+
+ if (strchr (cmd, '/'))
+ {
+ result = (0 == stat (cmd, &st));
+ goto DONE;
+ }
+
+ path = getenv("PATH");
+ if (!path || !*path)
+ goto DONE;
+
+ L = strlen (cmd);
+ path = strdup (path);
+ token = strtok (path, ":");
+
+ while (token)
+ {
+ char *p2 = (char *) malloc (strlen (token) + L + 3);
+ strcpy (p2, token);
+ strcat (p2, "/");
+ strcat (p2, cmd);
+ result = (0 == stat (p2, &st));
+ if (result)
+ goto DONE;
+ token = strtok (0, ":");
+ }
+
+ DONE:
+ free (cmd);
+ if (path) free (path);
+ return result;
+}
+
+
static void
populate_hack_list (state *s)
{
+#ifdef HAVE_GTK2
+ saver_preferences *p = &s->prefs;
+ GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list"));
+ GtkListStore *model;
+ GtkTreeSelection *selection;
+ GtkCellRenderer *ren;
+ GtkTreeIter iter;
+ int i;
+
+ g_object_get (G_OBJECT (list),
+ "model", &model,
+ NULL);
+ if (!model)
+ {
+ model = gtk_list_store_new (COL_LAST, G_TYPE_BOOLEAN, G_TYPE_STRING);
+ g_object_set (G_OBJECT (list), "model", model, NULL);
+ g_object_unref (model);
+
+ ren = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_insert_column_with_attributes (list, COL_ENABLED,
+ _("Use"), ren,
+ "active", COL_ENABLED,
+ NULL);
+
+ g_signal_connect (ren, "toggled",
+ G_CALLBACK (list_checkbox_cb),
+ s);
+
+ ren = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (list, COL_NAME,
+ _("Screen Saver"), ren,
+ "markup", COL_NAME,
+ NULL);
+
+ g_signal_connect_after (list, "row_activated",
+ G_CALLBACK (list_activated_cb),
+ s);
+
+ selection = gtk_tree_view_get_selection (list);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (list_select_changed_cb),
+ s);
+
+ }
+
+ for (i = 0; i < s->list_count; i++)
+ {
+ int hack_number = s->list_elt_to_hack_number[i];
+ screenhack *hack = (hack_number < 0 ? 0 : p->screenhacks[hack_number]);
+ char *pretty_name;
+ Bool available_p = (hack && s->hacks_available_p [hack_number]);
+
+ if (!hack) continue;
+
+ /* If we're to suppress uninstalled hacks, check $PATH now. */
+ if (p->ignore_uninstalled_p && !available_p)
+ continue;
+
+ pretty_name = (hack->name
+ ? strdup (hack->name)
+ : make_hack_name (hack->command));
+
+ if (!available_p)
+ {
+ /* Make the text foreground be the color of insensitive widgets
+ (but don't actually make it be insensitive, since we still
+ want to be able to click on it.)
+ */
+ GtkStyle *style = GTK_WIDGET (list)->style;
+ GdkColor *fg = &style->fg[GTK_STATE_INSENSITIVE];
+ /* GdkColor *bg = &style->bg[GTK_STATE_INSENSITIVE]; */
+ char *buf = (char *) malloc (strlen (pretty_name) + 100);
+
+ sprintf (buf, "<span foreground=\"#%02X%02X%02X\""
+ /* " background=\"#%02X%02X%02X\"" */
+ ">%s</span>",
+ fg->red >> 8, fg->green >> 8, fg->blue >> 8,
+ /* bg->red >> 8, bg->green >> 8, bg->blue >> 8, */
+ pretty_name);
+ free (pretty_name);
+ pretty_name = buf;
+ }
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COL_ENABLED, hack->enabled_p,
+ COL_NAME, pretty_name,
+ -1);
+ free (pretty_name);
+ }
+
+#else /* !HAVE_GTK2 */
+
saver_preferences *p = &s->prefs;
GtkList *list = GTK_LIST (name_to_widget (s, "list"));
int i;
- for (i = 0; i < p->screenhacks_count; i++)
+ for (i = 0; i < s->list_count; i++)
{
- screenhack *hack = p->screenhacks[s->list_elt_to_hack_number[i]];
+ int hack_number = s->list_elt_to_hack_number[i];
+ screenhack *hack = (hack_number < 0 ? 0 : p->screenhacks[hack_number]);
/* A GtkList must contain only GtkListItems, but those can contain
an arbitrary widget. We add an Hbox, and inside that, a Checkbox
GtkWidget *line_hbox;
GtkWidget *line_check;
GtkWidget *line_label;
+ char *pretty_name;
+ Bool available_p = (hack && s->hacks_available_p [hack_number]);
- char *pretty_name = (hack->name
- ? strdup (hack->name)
- : make_hack_name (hack->command));
+ if (!hack) continue;
+
+ /* If we're to suppress uninstalled hacks, check $PATH now. */
+ if (p->ignore_uninstalled_p && !available_p)
+ continue;
+
+ pretty_name = (hack->name
+ ? strdup (hack->name)
+ : make_hack_name (hack->command));
line = gtk_list_item_new ();
line_hbox = gtk_hbox_new (FALSE, 0);
GTK_SIGNAL_FUNC (list_checkbox_cb),
(gpointer) s);
-#if 0 /* #### */
- GTK_WIDGET (GTK_BIN(line)->child)->style =
- gtk_style_copy (GTK_WIDGET (text_line)->style);
-#endif
gtk_widget_show (line);
+
+ if (!available_p)
+ {
+ /* Make the widget be colored like insensitive widgets
+ (but don't actually make it be insensitive, since we
+ still want to be able to click on it.)
+ */
+ GtkRcStyle *rc_style;
+ GdkColor fg, bg;
+
+ gtk_widget_realize (GTK_WIDGET (line_label));
+
+ fg = GTK_WIDGET (line_label)->style->fg[GTK_STATE_INSENSITIVE];
+ bg = GTK_WIDGET (line_label)->style->bg[GTK_STATE_INSENSITIVE];
+
+ rc_style = gtk_rc_style_new ();
+ rc_style->fg[GTK_STATE_NORMAL] = fg;
+ rc_style->bg[GTK_STATE_NORMAL] = bg;
+ rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG|GTK_RC_BG;
+
+ gtk_widget_modify_style (GTK_WIDGET (line_label), rc_style);
+ gtk_rc_style_unref (rc_style);
+ }
}
gtk_signal_connect (GTK_OBJECT (list), "select_child",
gtk_signal_connect (GTK_OBJECT (list), "unselect_child",
GTK_SIGNAL_FUNC (list_unselect_cb),
(gpointer) s);
+#endif /* !HAVE_GTK2 */
}
-
static void
update_list_sensitivity (state *s)
{
Bool checkable = (p->mode == RANDOM_HACKS);
Bool blankable = (p->mode != DONT_BLANK);
+#ifndef HAVE_GTK2
GtkWidget *head = name_to_widget (s, "col_head_hbox");
GtkWidget *use = name_to_widget (s, "use_col_frame");
+#endif /* HAVE_GTK2 */
GtkWidget *scroller = name_to_widget (s, "scroller");
GtkWidget *buttons = name_to_widget (s, "next_prev_hbox");
GtkWidget *blanker = name_to_widget (s, "blanking_table");
+#ifdef HAVE_GTK2
+ GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list"));
+ GtkTreeViewColumn *use = gtk_tree_view_get_column (list, COL_ENABLED);
+#else /* !HAVE_GTK2 */
GtkList *list = GTK_LIST (name_to_widget (s, "list"));
GList *kids = gtk_container_children (GTK_CONTAINER (list));
gtk_widget_set_sensitive (GTK_WIDGET (head), sensitive);
+#endif /* !HAVE_GTK2 */
gtk_widget_set_sensitive (GTK_WIDGET (scroller), sensitive);
gtk_widget_set_sensitive (GTK_WIDGET (buttons), sensitive);
gtk_widget_set_sensitive (GTK_WIDGET (blanker), blankable);
+#ifdef HAVE_GTK2
+ gtk_tree_view_column_set_visible (use, checkable);
+#else /* !HAVE_GTK2 */
if (checkable)
gtk_widget_show (use); /* the "Use" column header */
else
kids = kids->next;
}
+#endif /* !HAVE_GTK2 */
}
populate_prefs_page (state *s)
{
saver_preferences *p = &s->prefs;
- char str[100];
+
+ Bool can_lock_p = True;
+
+ /* Disable all the "lock" controls if locking support was not provided
+ at compile-time, or if running on MacOS. */
+# if defined(NO_LOCKING) || defined(__APPLE__)
+ can_lock_p = False;
+# endif
+
+
+ /* The file supports timeouts of less than a minute, but the GUI does
+ not, so throttle the values to be at least one minute (since "0" is
+ a bad rounding choice...)
+ */
+# define THROTTLE(NAME) if (p->NAME != 0 && p->NAME < 60000) p->NAME = 60000
+ THROTTLE (timeout);
+ THROTTLE (cycle);
+ /* THROTTLE (passwd_timeout); */ /* GUI doesn't set this; leave it alone */
+# undef THROTTLE
# define FMT_MINUTES(NAME,N) \
- sprintf (str, "%d", ((N) + 59) / (60 * 1000)); \
- gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, (NAME))), str)
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (name_to_widget (s, (NAME))), (double)((N) + 59) / (60 * 1000))
# define FMT_SECONDS(NAME,N) \
- sprintf (str, "%d", ((N) / 1000)); \
- gtk_entry_set_text (GTK_ENTRY (name_to_widget (s, (NAME))), str)
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (name_to_widget (s, (NAME))), (double)((N) / 1000))
FMT_MINUTES ("timeout_spinbutton", p->timeout);
FMT_MINUTES ("cycle_spinbutton", p->cycle);
{
Bool found_any_writable_cells = False;
+ Bool fading_possible = False;
Bool dpms_supported = False;
Display *dpy = GDK_DISPLAY();
}
}
+ fading_possible = found_any_writable_cells;
#ifdef HAVE_XF86VMODE_GAMMA
- found_any_writable_cells = True; /* if we can gamma fade, go for it */
+ fading_possible = True;
#endif
#ifdef HAVE_DPMS_EXTENSION
/* Blanking and Locking
*/
- SENSITIZE ("lock_spinbutton", p->lock_p);
- SENSITIZE ("lock_mlabel", p->lock_p);
+ SENSITIZE ("lock_button", can_lock_p);
+ SENSITIZE ("lock_spinbutton", can_lock_p && p->lock_p);
+ SENSITIZE ("lock_mlabel", can_lock_p && p->lock_p);
/* DPMS
*/
/* Colormaps
*/
- SENSITIZE ("cmap_frame", found_any_writable_cells);
+ SENSITIZE ("cmap_frame", found_any_writable_cells || fading_possible);
SENSITIZE ("install_button", found_any_writable_cells);
- SENSITIZE ("fade_button", found_any_writable_cells);
- SENSITIZE ("unfade_button", found_any_writable_cells);
+ SENSITIZE ("fade_button", fading_possible);
+ SENSITIZE ("unfade_button", fading_possible);
- SENSITIZE ("fade_label", (found_any_writable_cells &&
+ SENSITIZE ("fade_label", (fading_possible &&
(p->fade_p || p->unfade_p)));
- SENSITIZE ("fade_spinbutton", (found_any_writable_cells &&
+ SENSITIZE ("fade_spinbutton", (fading_possible &&
(p->fade_p || p->unfade_p)));
# undef SENSITIZE
static void
populate_popup_window (state *s)
{
- saver_preferences *p = &s->prefs;
- GtkWidget *parent = name_to_widget (s, "settings_vbox");
GtkLabel *doc = GTK_LABEL (name_to_widget (s, "doc"));
- int list_elt = selected_list_element (s);
- int hack_number = (list_elt >= 0 && list_elt < p->screenhacks_count
- ? s->list_elt_to_hack_number[list_elt]
- : -1);
- screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
char *doc_string = 0;
+ /* #### not in Gtk 1.2
+ gtk_label_set_selectable (doc);
+ */
+
# ifdef HAVE_XML
if (s->cdata)
{
s->cdata = 0;
}
- if (hack)
- {
- GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text"));
- const char *cmd_line = gtk_entry_get_text (GTK_ENTRY (cmd));
- s->cdata = load_configurator (cmd_line, s->debug_p);
- if (s->cdata && s->cdata->widget)
- gtk_box_pack_start (GTK_BOX (parent), s->cdata->widget, TRUE, TRUE, 0);
- }
+ {
+ saver_preferences *p = &s->prefs;
+ int list_elt = selected_list_element (s);
+ int hack_number = (list_elt >= 0 && list_elt < s->list_count
+ ? s->list_elt_to_hack_number[list_elt]
+ : -1);
+ screenhack *hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
+ if (hack)
+ {
+ GtkWidget *parent = name_to_widget (s, "settings_vbox");
+ GtkWidget *cmd = GTK_WIDGET (name_to_widget (s, "cmd_text"));
+ const char *cmd_line = gtk_entry_get_text (GTK_ENTRY (cmd));
+ s->cdata = load_configurator (cmd_line, s->debug_p);
+ if (s->cdata && s->cdata->widget)
+ gtk_box_pack_start (GTK_BOX (parent), s->cdata->widget,
+ TRUE, TRUE, 0);
+ }
+ }
doc_string = (s->cdata
? s->cdata->description
: 0);
# else /* !HAVE_XML */
- doc_string = "Descriptions not available: no XML support compiled in.";
+ doc_string = _("Descriptions not available: no XML support compiled in.");
# endif /* !HAVE_XML */
gtk_label_set_text (doc, (doc_string
- ? doc_string
- : "No description available."));
+ ? _(doc_string)
+ : _("No description available.")));
}
static void
fix_text_entry_sizes (state *s)
{
+ GtkWidget *w;
+
+# if 0 /* appears no longer necessary with Gtk 1.2.10 */
const char * const spinbuttons[] = {
"timeout_spinbutton", "cycle_spinbutton", "lock_spinbutton",
"dpms_standby_spinbutton", "dpms_suspend_spinbutton",
"-fade_spinbutton" };
int i;
int width = 0;
- GtkWidget *w;
for (i = 0; i < countof(spinbuttons); i++)
{
width = gdk_string_width (w->style->font, "mmmmmmmmmmmmmmmmmmmm");
gtk_widget_set_usize (w, width, -2);
- /* Now fix the height of the list.
+# endif /* 0 */
+
+ /* Now fix the height of the list widget:
+ make it default to being around 10 text-lines high instead of 4.
*/
+ w = GTK_WIDGET (name_to_widget (s, "list"));
{
int lines = 10;
int height;
int leading = 3; /* approximate is ok... */
int border = 2;
- w = GTK_WIDGET (name_to_widget (s, "list"));
+
+#ifdef HAVE_GTK2
+ PangoFontMetrics *pain =
+ pango_context_get_metrics (gtk_widget_get_pango_context (w),
+ w->style->font_desc,
+ gtk_get_default_language ());
+ height = PANGO_PIXELS (pango_font_metrics_get_ascent (pain) +
+ pango_font_metrics_get_descent (pain));
+#else /* !HAVE_GTK2 */
height = w->style->font->ascent + w->style->font->descent;
+#endif /* !HAVE_GTK2 */
+
height += leading;
height *= lines;
height += border * 2;
}
-
+#ifndef HAVE_GTK2
\f
/* Pixmaps for the up and down arrow buttons (yeah, this is sleazy...)
*/
state *s = (state *) user_data;
pixmapify_button (s, 0);
}
-
+#endif /* !HAVE_GTK2 */
\f
/* Work around a Gtk bug that causes label widgets to wrap text too early.
gtk_object_set_data (GTK_OBJECT (label), "gtk-aux-info", aux_info);
gtk_signal_connect (GTK_OBJECT (label), "size_allocate",
- you_are_not_a_unique_or_beautiful_snowflake,
+ GTK_SIGNAL_FUNC (you_are_not_a_unique_or_beautiful_snowflake),
0);
gtk_widget_set_usize (GTK_WIDGET (label), -2, -2);
if (p->mode == BLANK_ONLY)
{
hack = 0;
- pretty_name = strdup ("Blank Screen");
+ pretty_name = strdup (_("Blank Screen"));
schedule_preview (s, 0);
}
else if (p->mode == DONT_BLANK)
{
hack = 0;
- pretty_name = strdup ("Screen Saver Disabled");
+ pretty_name = strdup (_("Screen Saver Disabled"));
schedule_preview (s, 0);
}
else
{
- int hack_number = (list_elt >= 0 && list_elt < p->screenhacks_count
+ int hack_number = (list_elt >= 0 && list_elt < s->list_count
? s->list_elt_to_hack_number[list_elt]
: -1);
hack = (hack_number >= 0 ? p->screenhacks[hack_number] : 0);
}
if (!pretty_name)
- pretty_name = strdup ("Preview");
+ pretty_name = strdup (_("Preview"));
- gtk_frame_set_label (frame1, pretty_name);
- gtk_frame_set_label (frame2, pretty_name);
+ gtk_frame_set_label (frame1, _(pretty_name));
+ gtk_frame_set_label (frame2, _(pretty_name));
gtk_entry_set_text (cmd, (hack ? hack->command : ""));
gtk_entry_set_position (cmd, 0);
{
char title[255];
- sprintf (title, "%s: %.100s Settings",
+ sprintf (title, _("%s: %.100s Settings"),
progclass, (pretty_name ? pretty_name : "???"));
gtk_window_set_title (GTK_WINDOW (s->popup_widget), title);
}
(hack
? (hack->visual && *hack->visual
? hack->visual
- : "Any")
+ : _("Any"))
: ""));
sensitize_demo_widgets (s, (hack ? True : False));
if (a == b)
return 0;
else
- return strcmp (sort_hack_cmp_names_kludge[*(int *) a],
- sort_hack_cmp_names_kludge[*(int *) b]);
+ {
+ int aa = *(int *) a;
+ int bb = *(int *) b;
+ const char last[] = "\377\377\377\377\377\377\377\377\377\377\377";
+ return strcmp ((aa < 0 ? last : sort_hack_cmp_names_kludge[aa]),
+ (bb < 0 ? last : sort_hack_cmp_names_kludge[bb]));
+ }
}
initialize_sort_map (state *s)
{
saver_preferences *p = &s->prefs;
- int i;
+ int i, j;
if (s->list_elt_to_hack_number) free (s->list_elt_to_hack_number);
if (s->hack_number_to_list_elt) free (s->hack_number_to_list_elt);
+ if (s->hacks_available_p) free (s->hacks_available_p);
s->list_elt_to_hack_number = (int *)
calloc (sizeof(int), p->screenhacks_count + 1);
s->hack_number_to_list_elt = (int *)
calloc (sizeof(int), p->screenhacks_count + 1);
+ s->hacks_available_p = (Bool *)
+ calloc (sizeof(Bool), p->screenhacks_count + 1);
- /* Initialize table to 1:1 mapping */
+ /* Check which hacks actually exist on $PATH
+ */
for (i = 0; i < p->screenhacks_count; i++)
- s->list_elt_to_hack_number[i] = i;
+ {
+ screenhack *hack = p->screenhacks[i];
+ s->hacks_available_p[i] = on_path_p (hack->command);
+ }
+
+ /* Initialize list->hack table to unsorted mapping, omitting nonexistent
+ hacks, if desired.
+ */
+ j = 0;
+ for (i = 0; i < p->screenhacks_count; i++)
+ {
+ if (!p->ignore_uninstalled_p ||
+ s->hacks_available_p[i])
+ s->list_elt_to_hack_number[j++] = i;
+ }
+ s->list_count = j;
- /* Generate list of names (once)
+ for (; j < p->screenhacks_count; j++)
+ s->list_elt_to_hack_number[j] = -1;
+
+
+ /* Generate list of sortable names (once)
*/
sort_hack_cmp_names_kludge = (char **)
calloc (sizeof(char *), p->screenhacks_count);
sort_hack_cmp_names_kludge[i] = name;
}
- /* Sort alphabetically
+ /* Sort list->hack map alphabetically
*/
qsort (s->list_elt_to_hack_number,
p->screenhacks_count,
const char *f = init_file_name();
char *b;
int list_elt;
- GtkList *list;
+ GtkWidget *list;
if (!f || !*f) return 0;
b = (char *) malloc (strlen(f) + 1024);
sprintf (b,
- "Warning:\n\n"
- "file \"%s\" has changed, reloading.\n",
+ _("Warning:\n\n"
+ "file \"%s\" has changed, reloading.\n"),
f);
warning_dialog (s->toplevel_widget, b, False, 100);
free (b);
initialize_sort_map (s);
list_elt = selected_list_element (s);
- list = GTK_LIST (name_to_widget (s, "list"));
+ list = name_to_widget (s, "list");
gtk_container_foreach (GTK_CONTAINER (list), widget_deleter, NULL);
populate_hack_list (s);
force_list_select_item (s, list, list_elt, True);
populate_prefs_page (s);
populate_demo_window (s, list_elt);
- ensure_selected_item_visible (GTK_WIDGET (list));
+ ensure_selected_item_visible (list);
status = 1;
}
gdk_window_set_background (window, &p->style->bg[GTK_STATE_NORMAL]);
gdk_window_clear (window);
- if (s->running_preview_error_p)
- {
- const char * const lines[] = { "No Preview", "Available" };
- int lh = p->style->font->ascent + p->style->font->descent;
- int y, i;
- gint w, h;
- gdk_window_get_size (window, &w, &h);
- y = (h - (lh * countof(lines))) / 2;
- y += p->style->font->ascent;
- for (i = 0; i < countof(lines); i++)
- {
- int sw = gdk_string_width (p->style->font, lines[i]);
- int x = (w - sw) / 2;
- gdk_draw_string (window, p->style->font,
- p->style->fg_gc[GTK_STATE_NORMAL],
- x, y, lines[i]);
- y += lh;
- }
- }
+ {
+ int list_elt = selected_list_element (s);
+ int hack_number = (list_elt >= 0
+ ? s->list_elt_to_hack_number[list_elt]
+ : -1);
+ Bool available_p = (hack_number >= 0
+ ? s->hacks_available_p [hack_number]
+ : True);
+#ifdef HAVE_GTK2
+ GtkWidget *notebook = name_to_widget (s, "preview_notebook");
+ gtk_notebook_set_page (GTK_NOTEBOOK (notebook),
+ (s->running_preview_error_p
+ ? (available_p ? 1 : 2)
+ : 0));
+#else /* !HAVE_GTK2 */
+ if (s->running_preview_error_p)
+ {
+ const char * const lines1[] = { N_("No Preview"), N_("Available") };
+ const char * const lines2[] = { N_("Not"), N_("Installed") };
+ int nlines = countof(lines1);
+ int lh = p->style->font->ascent + p->style->font->descent;
+ int y, i;
+ gint w, h;
+
+ const char * const *lines = (available_p ? lines1 : lines2);
+
+ gdk_window_get_size (window, &w, &h);
+ y = (h - (lh * nlines)) / 2;
+ y += p->style->font->ascent;
+ for (i = 0; i < nlines; i++)
+ {
+ int sw = gdk_string_width (p->style->font, _(lines[i]));
+ int x = (w - sw) / 2;
+ gdk_draw_string (window, p->style->font,
+ p->style->fg_gc[GTK_STATE_NORMAL],
+ x, y, _(lines[i]));
+ y += lh;
+ }
+ }
+#endif /* !HAVE_GTK2 */
+ }
gdk_flush ();
+}
+
- /* Is there a GDK way of doing this? */
- XSync (GDK_DISPLAY(), False);
+static void
+reset_preview_window (state *s)
+{
+ /* On some systems (most recently, MacOS X) OpenGL programs get confused
+ when you kill one and re-start another on the same window. So maybe
+ it's best to just always destroy and recreate the preview window
+ when changing hacks, instead of always trying to reuse the same one?
+ */
+ GtkWidget *pr = name_to_widget (s, "preview");
+ if (GTK_WIDGET_REALIZED (pr))
+ {
+ Window oid = (pr->window ? GDK_WINDOW_XWINDOW (pr->window) : 0);
+ Window id;
+ gtk_widget_hide (pr);
+ gtk_widget_unrealize (pr);
+ gtk_widget_realize (pr);
+ gtk_widget_show (pr);
+ id = (pr->window ? GDK_WINDOW_XWINDOW (pr->window) : 0);
+ if (s->debug_p)
+ fprintf (stderr, "%s: window id 0x%X -> 0x%X\n", blurb(),
+ (unsigned int) oid,
+ (unsigned int) id);
+ }
}
style->fg_gc[GTK_STATE_NORMAL] = fgc;
style->bg_gc[GTK_STATE_NORMAL] = fgc;
gtk_widget_set_style (widget, style);
+
+ /* For debugging purposes, put a title on the window (so that
+ it can be easily found in the output of "xwininfo -tree".)
+ */
+ gdk_window_set_title (window, "Preview");
}
gtk_widget_show (widget);
char *ss = strchr (ps, ' ');
if (ss) *ss = 0;
ss = strrchr (ps, '/');
- if (ss) *ss = 0;
- else ss = ps;
+ if (!ss)
+ ss = ps;
+ else
+ {
+ ss = strdup (ss+1);
+ free (ps);
+ }
return ss;
}
else
if (pid == s->running_preview_pid)
{
char *ss = subproc_pretty_name (s);
- fprintf (stderr, "%s: pid %lu (%s) died\n", blurb(), pid, ss);
+ fprintf (stderr, "%s: pid %lu (%s) died\n", blurb(),
+ (unsigned long) pid, ss);
free (ss);
}
else
- fprintf (stderr, "%s: pid %lu died\n", blurb(), pid);
+ fprintf (stderr, "%s: pid %lu died\n", blurb(),
+ (unsigned long) pid);
}
}
}
sprintf (buf, "%s: running %s", blurb(), av[0]);
perror (buf);
}
- exit (1); /* exits fork */
+
+ /* Note that one must use _exit() instead of exit() in procs forked
+ off of Gtk programs -- Gtk installs an atexit handler that has a
+ copy of the X connection (which we've already closed, for safety.)
+ If one uses exit() instead of _exit(), then one sometimes gets a
+ spurious "Gdk-ERROR: Fatal IO error on X server" error message.
+ */
+ _exit (1); /* exits fork */
break;
}
default:
int wait_status = 0;
FILE *f = fdopen (in, "r");
- unsigned long v = 0;
+ unsigned int v = 0;
char c;
close (out); /* don't need this one */
static void
-kill_preview_subproc (state *s)
+kill_preview_subproc (state *s, Bool reset_p)
{
s->running_preview_error_p = False;
{
if (s->debug_p)
fprintf (stderr, "%s: pid %lu (%s) was already dead.\n",
- blurb(), s->running_preview_pid, ss);
+ blurb(), (unsigned long) s->running_preview_pid, ss);
}
else
{
char buf [1024];
sprintf (buf, "%s: couldn't kill pid %lu (%s)",
- blurb(), s->running_preview_pid, ss);
+ blurb(), (unsigned long) s->running_preview_pid, ss);
perror (buf);
}
}
else if (s->debug_p)
fprintf (stderr, "%s: killed pid %lu (%s)\n", blurb(),
- s->running_preview_pid, ss);
+ (unsigned long) s->running_preview_pid, ss);
free (ss);
s->running_preview_pid = 0;
}
reap_zombies (s);
-}
-
-static void
-exec_program (const char *cmd, int nice_level)
-{
- char *av[1024];
- int ac = 0;
- char *token = strtok (strdup(cmd), " \t");
- while (token)
+ if (reset_p)
{
- av[ac++] = token;
- token = strtok(0, " \t");
+ reset_preview_window (s);
+ clear_preview_window (s);
}
- av[ac] = 0;
-
- nice (nice_level - nice (0));
-
- usleep (250000); /* pause for 1/4th second before launching, to give the
- previous program time to die and flush its X buffer,
- so we don't get leftover turds on the window. */
-
- execvp (av[0], av); /* shouldn't return. */
-
- {
- char buf [512];
- sprintf (buf, "%s: could not execute \"%s\"", blurb(), av[0]);
- perror (buf);
- }
- fflush(stderr);
- fflush(stdout);
- exit (1); /* Note that this only exits a child fork. */
}
{
saver_preferences *p = &s->prefs;
Window id;
- Bool hairy_p;
- char *new_cmd;
+ char *new_cmd = 0;
pid_t forked;
- int nice_level = nice (0) - p->nice_inferior;
const char *cmd = s->desired_preview_cmd;
GtkWidget *pr = name_to_widget (s, "preview");
- GdkWindow *window = pr->window;
+ GdkWindow *window;
+
+ reset_preview_window (s);
+
+ window = pr->window;
s->running_preview_error_p = False;
if (s->preview_suppressed_p)
{
- kill_preview_subproc (s);
- return;
+ kill_preview_subproc (s, False);
+ goto DONE;
}
new_cmd = malloc (strlen (cmd) + 40);
else
{
strcpy (new_cmd, cmd);
- sprintf (new_cmd + strlen (new_cmd), " -window-id 0x%X", id);
+ sprintf (new_cmd + strlen (new_cmd), " -window-id 0x%X",
+ (unsigned int) id);
}
- hairy_p = (new_cmd && !!strpbrk (new_cmd, "*?$&!<>[];`'\\\"="));
- if (hairy_p)
- {
- /* Command requires a full shell? Forget it. */
- free (new_cmd);
- new_cmd = 0;
- if (s->debug_p)
- fprintf (stderr, "%s: command is hairy: not previewing\n", blurb());
- }
-
- kill_preview_subproc (s);
+ kill_preview_subproc (s, False);
if (! new_cmd)
{
s->running_preview_error_p = True;
clear_preview_window (s);
- return;
+ goto DONE;
}
switch ((int) (forked = fork ()))
sprintf (buf, "%s: couldn't fork", blurb());
perror (buf);
s->running_preview_error_p = True;
- return;
+ goto DONE;
+ break;
}
case 0:
{
close (ConnectionNumber (GDK_DISPLAY()));
- exec_program (new_cmd, nice_level);
- abort();
+
+ hack_subproc_environment (id, s->debug_p);
+
+ usleep (250000); /* pause for 1/4th second before launching, to give
+ the previous program time to die and flush its X
+ buffer, so we don't get leftover turds on the
+ window. */
+
+ exec_command (p->shell, new_cmd, p->nice_inferior);
+ /* Don't bother printing an error message when we are unable to
+ exec subprocesses; we handle that by polling the pid later.
+
+ Note that one must use _exit() instead of exit() in procs forked
+ off of Gtk programs -- Gtk installs an atexit handler that has a
+ copy of the X connection (which we've already closed, for safety.)
+ If one uses exit() instead of _exit(), then one sometimes gets a
+ spurious "Gdk-ERROR: Fatal IO error on X server" error message.
+ */
+ _exit (1); /* exits child fork */
break;
default:
if (s->debug_p)
{
char *ss = subproc_pretty_name (s);
- fprintf (stderr, "%s: forked %lu (%s)\n", blurb(), forked, ss);
+ fprintf (stderr, "%s: forked %lu (%s)\n", blurb(),
+ (unsigned long) forked, ss);
free (ss);
}
break;
}
schedule_preview_check (s);
+
+ DONE:
+ if (new_cmd) free (new_cmd);
+ new_cmd = 0;
}
if (s->debug_p)
fprintf (stderr, "%s: %s\n", blurb(), ndpy);
+ /* don't free(ndpy) -- some implementations of putenv (BSD 4.4, glibc
+ 2.0) copy the argument, but some (libc4,5, glibc 2.1.2) do not.
+ So we must leak it (and/or the previous setting). Yay.
+ */
+
if (def_path && *def_path)
{
const char *opath = getenv("PATH");
if (putenv (npath))
abort ();
+ /* do not free(npath) -- see above */
if (s->debug_p)
fprintf (stderr, "%s: added \"%s\" to $PATH\n", blurb(), def_path);
}
+static void
+hack_subproc_environment (Window preview_window_id, Bool debug_p)
+{
+ /* Store a window ID in $XSCREENSAVER_WINDOW -- this isn't strictly
+ necessary yet, but it will make programs work if we had invoked
+ them with "-root" and not with "-window-id" -- which, of course,
+ doesn't happen.
+ */
+ char *nssw = (char *) malloc (40);
+ sprintf (nssw, "XSCREENSAVER_WINDOW=0x%X", (unsigned int) preview_window_id);
+
+ /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
+ any more, right? It's not Posix, but everyone seems to have it. */
+ if (putenv (nssw))
+ abort ();
+
+ if (debug_p)
+ fprintf (stderr, "%s: %s\n", blurb(), nssw);
+
+ /* do not free(nssw) -- see above */
+}
+
+
/* Called from a timer:
Launches the currently-chosen subprocess, if it's not already running.
If there's a different process running, kills it.
{
state *s = (state *) data;
if (! s->desired_preview_cmd)
- kill_preview_subproc (s);
+ kill_preview_subproc (s, True);
else if (!s->running_preview_cmd ||
!!strcmp (s->desired_preview_cmd, s->running_preview_cmd))
launch_preview_subproc (s);
{
char *ss = subproc_pretty_name (s);
fprintf (stderr, "%s: timer: pid %lu (%s) is %s\n", blurb(),
- s->running_preview_pid, ss,
+ (unsigned long) s->running_preview_pid, ss,
(s->running_preview_error_p ? "dead" : "alive"));
free (ss);
}
Atom type;
int format;
unsigned long nitems, bytesafter;
- CARD32 *data = 0;
+ unsigned char *dataP = 0;
Display *dpy = GDK_DISPLAY();
Bool blanked_p = False;
XA_SCREENSAVER_STATUS,
0, 3, False, XA_INTEGER,
&type, &format, &nitems, &bytesafter,
- (unsigned char **) &data)
+ &dataP)
== Success
&& type == XA_INTEGER
&& nitems >= 3
- && data)
- blanked_p = (data[0] == XA_BLANK || data[0] == XA_LOCK);
+ && dataP)
+ {
+ Atom *data = (Atom *) dataP;
+ blanked_p = (data[0] == XA_BLANK || data[0] == XA_LOCK);
+ }
- if (data) free (data);
+ if (dataP) XFree (dataP);
return blanked_p;
}
{
if (s->debug_p)
fprintf (stderr, "%s: screen is blanked: killing preview\n", blurb());
- kill_preview_subproc (s);
+ kill_preview_subproc (s, True);
}
return True; /* re-execute timer */
the_network_is_not_the_computer (state *s)
{
Display *dpy = GDK_DISPLAY();
- char *rversion, *ruser, *rhost;
+ char *rversion = 0, *ruser = 0, *rhost = 0;
char *luser, *lhost;
char *msg = 0;
struct passwd *p = getpwuid (getuid ());
if (!rversion || !*rversion)
{
sprintf (msg,
- "Warning:\n\n"
- "The XScreenSaver daemon doesn't seem to be running\n"
- "on display \"%s\". Launch it now?",
+ _("Warning:\n\n"
+ "The XScreenSaver daemon doesn't seem to be running\n"
+ "on display \"%s\". Launch it now?"),
d);
}
else if (p && ruser && *ruser && !!strcmp (ruser, p->pw_name))
/* Warn that the two processes are running as different users.
*/
sprintf(msg,
- "Warning:\n\n"
+ _("Warning:\n\n"
"%s is running as user \"%s\" on host \"%s\".\n"
"But the xscreensaver managing display \"%s\"\n"
"is running as user \"%s\" on host \"%s\".\n"
"You should either re-run %s as \"%s\", or re-run\n"
"xscreensaver as \"%s\".\n"
"\n"
- "Restart the xscreensaver daemon now?\n",
- blurb(), luser, lhost,
+ "Restart the xscreensaver daemon now?\n"),
+ progname, luser, lhost,
d,
(ruser ? ruser : "???"), (rhost ? rhost : "???"),
- blurb(),
- blurb(), (ruser ? ruser : "???"),
+ progname,
+ progname, (ruser ? ruser : "???"),
luser);
}
else if (rhost && *rhost && !!strcmp (rhost, lhost))
/* Warn that the two processes are running on different hosts.
*/
sprintf (msg,
- "Warning:\n\n"
+ _("Warning:\n\n"
"%s is running as user \"%s\" on host \"%s\".\n"
"But the xscreensaver managing display \"%s\"\n"
"is running as user \"%s\" on host \"%s\".\n"
"if they don't see the same ~%s/.xscreensaver file) then\n"
"%s won't work right.\n"
"\n"
- "Restart the daemon on \"%s\" as \"%s\" now?\n",
- blurb(), luser, lhost,
+ "Restart the daemon on \"%s\" as \"%s\" now?\n"),
+ progname, luser, lhost,
d,
(ruser ? ruser : "???"), (rhost ? rhost : "???"),
luser,
- blurb(),
+ progname,
lhost, luser);
}
else if (!!strcmp (rversion, s->short_version))
/* Warn that the version numbers don't match.
*/
sprintf (msg,
- "Warning:\n\n"
+ _("Warning:\n\n"
"This is %s version %s.\n"
"But the xscreensaver managing display \"%s\"\n"
"is version %s. This could cause problems.\n"
- "\n"
- "Restart the xscreensaver daemon now?\n",
- blurb(), s->short_version,
+ "\n"
+ "Restart the xscreensaver daemon now?\n"),
+ progname, s->short_version,
d,
rversion);
}
if (*msg)
warning_dialog (s->toplevel_widget, msg, True, 1);
+ if (rversion) free (rversion);
+ if (ruser) free (ruser);
+ if (rhost) free (rhost);
free (msg);
}
{
state *s = global_state_kludge; /* I hate C so much... */
fprintf (stderr, "\nX error in %s:\n", blurb());
- if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
- {
- kill_preview_subproc (s);
- exit (-1);
- }
- else
- fprintf (stderr, " (nonfatal.)\n");
+ XmuPrintDefaultErrorMessage (dpy, error, stderr);
+ kill_preview_subproc (s, False);
+ exit (-1);
return 0;
}
}
+#ifdef __GNUC__
+ __extension__ /* shut up about "string length is greater than the length
+ ISO C89 compilers are required to support" when including
+ the .ad file... */
+#endif
+
static char *defaults[] = {
#include "XScreenSaver_ad.h"
0
# ifdef HAVE_CRAPPLET
" [--crapplet]"
# endif
- " [--debug]";
-
+ "\n\t\t [--debug] [--sync] [--no-xshm] [--configdir dir]";
static void
map_popup_window_cb (GtkWidget *w, gpointer user_data)
return FALSE; /* do not re-execute timer */
}
+#ifdef HAVE_GTK2
+
+GtkWidget *
+create_xscreensaver_demo (void)
+{
+ GtkWidget *nb;
+
+ nb = name_to_widget (global_state_kludge, "preview_notebook");
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (nb), FALSE);
+
+ return name_to_widget (global_state_kludge, "xscreensaver_demo");
+}
+
+GtkWidget *
+create_xscreensaver_settings_dialog (void)
+{
+ GtkWidget *w, *box;
+
+ box = name_to_widget (global_state_kludge, "dialog_action_area");
+
+ w = name_to_widget (global_state_kludge, "adv_button");
+ gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (box), w, TRUE);
+
+ w = name_to_widget (global_state_kludge, "std_button");
+ gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (box), w, TRUE);
+
+ return name_to_widget (global_state_kludge, "xscreensaver_settings_dialog");
+}
+
+#endif /* HAVE_GTK2 */
int
main (int argc, char **argv)
Display *dpy;
Widget toplevel_shell;
char *real_progname = argv[0];
- char window_title[255];
+ char *window_title;
+ char *geom = 0;
Bool crapplet_p = False;
char *str;
+#ifdef ENABLE_NLS
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+
+# ifdef HAVE_GTK2
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+# else /* !HAVE_GTK2 */
+ if (!setlocale (LC_ALL, ""))
+ fprintf (stderr, "%s: locale not supported by C library\n", real_progname);
+# endif /* !HAVE_GTK2 */
+
+#endif /* ENABLE_NLS */
+
str = strrchr (real_progname, '/');
if (str) real_progname = str+1;
}
#ifdef DEFAULT_ICONDIR /* from -D on compile line */
- add_pixmap_directory (DEFAULT_ICONDIR);
-#endif
+# ifndef HAVE_GTK2
+ {
+ const char *dir = DEFAULT_ICONDIR;
+ if (*dir) add_pixmap_directory (dir);
+ }
+# endif /* !HAVE_GTK2 */
+#endif /* DEFAULT_ICONDIR */
/* This is gross, but Gtk understands --display and not -display...
*/
/* We need to parse this arg really early... Sigh. */
for (i = 1; i < argc; i++)
- if (argv[i] &&
- (!strcmp(argv[i], "--crapplet") ||
- !strcmp(argv[i], "--capplet")))
- {
-# ifdef HAVE_CRAPPLET
- int j;
- crapplet_p = True;
- for (j = i; j < argc; j++) /* remove it from the list */
- argv[j] = argv[j+1];
- argc--;
-
-# else /* !HAVE_CRAPPLET */
- fprintf (stderr, "%s: not compiled with --crapplet support\n",
- real_progname);
- fprintf (stderr, "%s: %s\n", real_progname, usage);
- exit (1);
-# endif /* !HAVE_CRAPPLET */
- }
- else if (argv[i] &&
- (!strcmp(argv[i], "--debug") ||
- !strcmp(argv[i], "-debug") ||
- !strcmp(argv[i], "-d")))
{
- int j;
- s->debug_p = True;
- for (j = i; j < argc; j++) /* remove it from the list */
- argv[j] = argv[j+1];
- argc--;
+ if (argv[i] &&
+ (!strcmp(argv[i], "--crapplet") ||
+ !strcmp(argv[i], "--capplet")))
+ {
+# if defined(HAVE_CRAPPLET) || defined(HAVE_GTK2)
+ int j;
+ crapplet_p = True;
+ for (j = i; j < argc; j++) /* remove it from the list */
+ argv[j] = argv[j+1];
+ argc--;
+# else /* !HAVE_CRAPPLET && !HAVE_GTK2 */
+ fprintf (stderr, "%s: not compiled with --crapplet support\n",
+ real_progname);
+ fprintf (stderr, "%s: %s\n", real_progname, usage);
+ exit (1);
+# endif /* !HAVE_CRAPPLET && !HAVE_GTK2 */
+ }
+ else if (argv[i] &&
+ (!strcmp(argv[i], "--debug") ||
+ !strcmp(argv[i], "-debug") ||
+ !strcmp(argv[i], "-d")))
+ {
+ int j;
+ s->debug_p = True;
+ for (j = i; j < argc; j++) /* remove it from the list */
+ argv[j] = argv[j+1];
+ argc--;
+ i--;
+ }
+ else if (argv[i] &&
+ argc > i+1 &&
+ *argv[i+1] &&
+ (!strcmp(argv[i], "-geometry") ||
+ !strcmp(argv[i], "-geom") ||
+ !strcmp(argv[i], "-geo") ||
+ !strcmp(argv[i], "-g")))
+ {
+ int j;
+ geom = argv[i+1];
+ for (j = i; j < argc; j++) /* remove them from the list */
+ argv[j] = argv[j+2];
+ argc -= 2;
+ i -= 2;
+ }
+ else if (argv[i] &&
+ argc > i+1 &&
+ *argv[i+1] &&
+ (!strcmp(argv[i], "--configdir")))
+ {
+ int j;
+ struct stat st;
+ hack_configuration_path = argv[i+1];
+ for (j = i; j < argc; j++) /* remove them from the list */
+ argv[j] = argv[j+2];
+ argc -= 2;
+ i -= 2;
+
+ if (0 != stat (hack_configuration_path, &st))
+ {
+ char buf[255];
+ sprintf (buf, "%s: %.200s", blurb(), hack_configuration_path);
+ perror (buf);
+ exit (1);
+ }
+ else if (!S_ISDIR (st.st_mode))
+ {
+ fprintf (stderr, "%s: not a directory: %s\n",
+ blurb(), hack_configuration_path);
+ exit (1);
+ }
+ }
}
+
+ if (s->debug_p)
+ fprintf (stderr, "%s: using config directory \"%s\"\n",
+ progname, hack_configuration_path);
+
+
/* Let Gtk open the X connection, then initialize Xt to use that
same connection. Doctor Frankenstein would be proud.
*/
;
else
{
- fprintf (stderr, "%s: unknown option: %s\n", real_progname, argv[i]);
+ fprintf (stderr, _("%s: unknown option: %s\n"), real_progname,
+ argv[i]);
fprintf (stderr, "%s: %s\n", real_progname, usage);
exit (1);
}
was in argv[0].
*/
p->db = db;
+
+ hack_environment (s); /* must be before initialize_sort_map() */
+
load_init_file (p);
initialize_sort_map (s);
/* Set the main window's title. */
{
+ char *base_title = _("Screensaver Preferences");
char *v = (char *) strdup(strchr(screensaver_id, ' '));
char *s1, *s2, *s3, *s4;
s1 = (char *) strchr(v, ' '); s1++;
s4 = (char *) strchr(s3, ')');
*s2 = 0;
*s4 = 0;
- sprintf (window_title, "%.50s %.50s, %.50s", progclass, s1, s3);
+
+ window_title = (char *) malloc (strlen (base_title) +
+ strlen (progclass) +
+ strlen (s1) + strlen (s3) +
+ 100);
+ sprintf (window_title, "%s (%s %s, %s)", base_title, progclass, s1, s3);
gtk_window_set_title (GTK_WINDOW (s->toplevel_widget), window_title);
gtk_window_set_title (GTK_WINDOW (s->popup_widget), window_title);
free (v);
"map", GTK_SIGNAL_FUNC(map_popup_window_cb),
(gpointer) s);
+#ifndef HAVE_GTK2
gtk_signal_connect (GTK_OBJECT (name_to_widget (s, "prev")),
"map", GTK_SIGNAL_FUNC(map_prev_button_cb),
(gpointer) s);
gtk_signal_connect (GTK_OBJECT (name_to_widget (s, "next")),
"map", GTK_SIGNAL_FUNC(map_next_button_cb),
(gpointer) s);
-
+#endif /* !HAVE_GTK2 */
/* Hook up callbacks to the items on the mode menu. */
{
capplet = capplet_widget_new ();
/* Make there be a "Close" button instead of "OK" and "Cancel" */
+# ifdef HAVE_CRAPPLET_IMMEDIATE
capplet_widget_changes_are_immediate (CAPPLET_WIDGET (capplet));
-
-# if 1
- /* In crapplet-mode, take off the menubar. */
- gtk_widget_hide (name_to_widget (s, "menubar"));
-# endif
+# endif /* HAVE_CRAPPLET_IMMEDIATE */
+ /* In crapplet-mode, take off the menubar. */
+ gtk_widget_hide (name_to_widget (s, "menubar"));
/* Reparent our top-level container to be a child of the capplet
window.
gtk_widget_ref (outer_vbox);
gtk_container_remove (GTK_CONTAINER (s->toplevel_widget),
outer_vbox);
- GTK_OBJECT_SET_FLAGS (outer_vbox, GTK_FLOATING);
+ STFU GTK_OBJECT_SET_FLAGS (outer_vbox, GTK_FLOATING);
gtk_container_add (GTK_CONTAINER (capplet), outer_vbox);
/* Find the window above us, and set the title and close handler. */
# endif /* HAVE_CRAPPLET */
+ /* The Gnome folks hate the menubar. I think it's important to have access
+ to the commands on the File menu (Restart Daemon, etc.) and to the
+ About and Documentation commands on the Help menu.
+ */
+#if 0
+#ifdef HAVE_GTK2
+ gtk_widget_hide (name_to_widget (s, "menubar"));
+#endif
+#endif
+
+ free (window_title);
+ window_title = 0;
+
+#ifdef HAVE_GTK2
+ /* After picking the default size, allow -geometry to override it. */
+ if (geom)
+ gtk_window_parse_geometry (GTK_WINDOW (s->toplevel_widget), geom);
+#endif
+
gtk_widget_show (s->toplevel_widget);
init_icon (GTK_WIDGET (s->toplevel_widget)->window); /* after `show' */
- hack_environment (s);
fix_preview_visual (s);
/* Realize page zero, so that we can diddle the scrollbar when the
int i;
for (i = 0; i < p->screenhacks_count; i++)
{
- screenhack *hack = p->screenhacks[s->hack_number_to_list_elt[i]];
+ screenhack *hack = p->screenhacks[i];
conf_data *d = load_configurator (hack->command, False);
if (d) free_conf_data (d);
}
# endif /* HAVE_CRAPPLET */
gtk_main ();
- kill_preview_subproc (s);
+ kill_preview_subproc (s, False);
exit (0);
}