/* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2005 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2008 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
/* from exec.c */
extern void exec_command (const char *shell, const char *command, int nice);
+extern int on_path_p (const char *program);
static void hack_subproc_environment (Window preview_window_id, Bool debug_p);
#define countof(x) (sizeof((x))/sizeof((*x)))
+/* You might think that to read an array of 32-bit quantities out of a
+ server-side property, you would pass an array of 32-bit data quantities
+ into XGetWindowProperty(). You would be wrong. You have to use an array
+ of longs, even if long is 64 bits (using 32 of each 64.)
+ */
+typedef long PROP32;
+
char *progname = 0;
char *progclass = "XScreenSaver";
XrmDatabase db;
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 total_available; /* how many 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. */
static void kill_preview_subproc (state *, Bool reset_p);
static void schedule_preview_check (state *);
+\f
+/* Prototypes of functions used by the Glade-generated code,
+ to avoid warnings.
+ */
+void exit_menu_cb (GtkMenuItem *, gpointer user_data);
+void about_menu_cb (GtkMenuItem *, gpointer user_data);
+void doc_menu_cb (GtkMenuItem *, gpointer user_data);
+void file_menu_cb (GtkMenuItem *, gpointer user_data);
+void activate_menu_cb (GtkMenuItem *, gpointer user_data);
+void lock_menu_cb (GtkMenuItem *, gpointer user_data);
+void kill_menu_cb (GtkMenuItem *, gpointer user_data);
+void restart_menu_cb (GtkWidget *, gpointer user_data);
+void run_this_cb (GtkButton *, gpointer user_data);
+void manual_cb (GtkButton *, gpointer user_data);
+void run_next_cb (GtkButton *, gpointer user_data);
+void run_prev_cb (GtkButton *, gpointer user_data);
+void pref_changed_cb (GtkWidget *, gpointer user_data);
+gboolean pref_changed_event_cb (GtkWidget *, GdkEvent *, gpointer user_data);
+void mode_menu_item_cb (GtkWidget *, gpointer user_data);
+void switch_page_cb (GtkNotebook *, GtkNotebookPage *,
+ gint page_num, gpointer user_data);
+void browse_image_dir_cb (GtkButton *, gpointer user_data);
+void browse_text_file_cb (GtkButton *, gpointer user_data);
+void browse_text_program_cb (GtkButton *, gpointer user_data);
+void settings_cb (GtkButton *, gpointer user_data);
+void settings_adv_cb (GtkButton *, gpointer user_data);
+void settings_std_cb (GtkButton *, gpointer user_data);
+void settings_switch_page_cb (GtkNotebook *, GtkNotebookPage *,
+ gint page_num, gpointer user_data);
+void settings_cancel_cb (GtkButton *, gpointer user_data);
+void settings_ok_cb (GtkButton *, gpointer user_data);
\f
/* Some random utility functions
*/
+const char *blurb (void);
+
const char *
blurb (void)
{
strcpy (buf, "Unknown error!");
warning_dialog (s->toplevel_widget, buf, False, 100);
}
- if (err) free (err);
}
else
{
look as good in the plain-old default Latin1 "C" locale.)
*/
#ifdef HAVE_GTK2
- sprintf(copy, ("Copyright \xC2\xA9 1991-2005 %s"), s);
+ sprintf(copy, ("Copyright \xC2\xA9 1991-2008 %s"), s);
#else /* !HAVE_GTK2 */
- sprintf(copy, ("Copyright \251 1991-2005 %s"), s);
+ sprintf(copy, ("Copyright \251 1991-2008 %s"), s);
#endif /* !HAVE_GTK2 */
sprintf (msg, "%s\n\n%s", copy, desc);
p->load_url_command,
p->help_url, p->help_url, p->help_url, p->help_url);
strcat (help_command, " ) &");
- system (help_command);
+ if (system (help_command) < 0)
+ fprintf (stderr, "%s: fork error\n", blurb());
free (help_command);
}
flush_dialog_changes_and_save (s);
xscreensaver_command (GDK_DISPLAY(), XA_EXIT, 0, False, NULL);
sleep (1);
- system ("xscreensaver -nosplash &");
+ if (system ("xscreensaver -nosplash &") < 0)
+ fprintf (stderr, "%s: fork error\n", blurb());
await_xscreensaver (s);
}
the length ISO C89 compilers are required to
support" in the following expression... */
# endif
- strcat (buf,
+ strcat (buf, STFU
_("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"
static int
demo_write_init_file (state *s, saver_preferences *p)
{
+ Display *dpy = GDK_DISPLAY();
#if 0
/* #### try to figure out why shit keeps getting reordered... */
abort();
#endif
- if (!write_init_file (p, s->short_version, False))
+ if (!write_init_file (dpy, p, s->short_version, False))
{
if (s->debug_p)
fprintf (stderr, "%s: wrote %s\n", blurb(), init_file_name());
G_MODULE_EXPORT void
manual_cb (GtkButton *button, gpointer user_data)
{
+ Display *dpy = GDK_DISPLAY();
state *s = global_state_kludge; /* I hate C so much... */
saver_preferences *p = &s->prefs;
GtkWidget *list_widget = name_to_widget (s, "list");
int list_elt = selected_list_element (s);
int hack_number;
char *name, *name2, *cmd, *str;
+ char *oname = 0;
if (list_elt < 0) return;
hack_number = s->list_elt_to_hack_number[list_elt];
name = strdup (p->screenhacks[hack_number]->command);
name2 = name;
+ oname = name;
while (isspace (*name2)) name2++;
str = name2;
while (*str && !isspace (*str)) str++;
*str = 0;
str = strrchr (name2, '/');
- if (str) name = str+1;
+ if (str) name2 = str+1;
- cmd = get_string_resource ("manualCommand", "ManualCommand");
+ cmd = get_string_resource (dpy, "manualCommand", "ManualCommand");
if (cmd)
{
char *cmd2 = (char *) malloc (strlen (cmd) + (strlen (name2) * 4) + 100);
cmd,
name2, name2, name2, name2);
strcat (cmd2, " ) &");
- system (cmd2);
+ if (system (cmd2) < 0)
+ fprintf (stderr, "%s: fork error\n", blurb());
free (cmd2);
}
else
False, 100);
}
- free (name);
+ free (oname);
}
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);
+ g_assert (model);
+ if (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 */
/* Callback on menu items in the "mode" options menu.
*/
-void
+G_MODULE_EXPORT void
mode_menu_item_cb (GtkWidget *widget, gpointer user_data)
{
state *s = (state *) user_data;
-G_MODULE_EXPORT void
+G_MODULE_EXPORT void
settings_cb (GtkButton *button, gpointer user_data)
{
state *s = global_state_kludge; /* I hate C so much... */
&& nitems >= 3
&& dataP)
{
- CARD32 *data = (CARD32 *) dataP;
+ PROP32 *data = (PROP32 *) dataP;
hack_number = (int) data[2] - 1;
}
}
-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)
{
+ Display *dpy = GDK_DISPLAY();
#ifdef HAVE_GTK2
saver_preferences *p = &s->prefs;
GtkTreeView *list = GTK_TREE_VIEW (name_to_widget (s, "list"));
pretty_name = (hack->name
? strdup (hack->name)
- : make_hack_name (hack->command));
+ : make_hack_name (dpy, hack->command));
if (!available_p)
{
static void
populate_demo_window (state *s, int list_elt)
{
+ Display *dpy = GDK_DISPLAY();
saver_preferences *p = &s->prefs;
screenhack *hack;
char *pretty_name;
pretty_name = (hack
? (hack->name
? strdup (hack->name)
- : make_hack_name (hack->command))
+ : make_hack_name (dpy, hack->command))
: 0);
if (hack)
static void
initialize_sort_map (state *s)
{
+ Display *dpy = GDK_DISPLAY();
saver_preferences *p = &s->prefs;
int i, j;
calloc (sizeof(int), p->screenhacks_count + 1);
s->hacks_available_p = (Bool *)
calloc (sizeof(Bool), p->screenhacks_count + 1);
+ s->total_available = 0;
/* Check which hacks actually exist on $PATH
*/
for (i = 0; i < p->screenhacks_count; i++)
{
screenhack *hack = p->screenhacks[i];
- s->hacks_available_p[i] = on_path_p (hack->command);
+ int on = on_path_p (hack->command) ? 1 : 0;
+ s->hacks_available_p[i] = on;
+ s->total_available += on;
}
/* Initialize list->hack table to unsorted mapping, omitting nonexistent
screenhack *hack = p->screenhacks[i];
char *name = (hack->name && *hack->name
? strdup (hack->name)
- : make_hack_name (hack->command));
+ : make_hack_name (dpy, hack->command));
char *str;
for (str = name; *str; str++)
*str = tolower(*str);
static int
maybe_reload_init_file (state *s)
{
+ Display *dpy = GDK_DISPLAY();
saver_preferences *p = &s->prefs;
int status = 0;
warning_dialog (s->toplevel_widget, b, False, 100);
free (b);
- load_init_file (p);
+ load_init_file (dpy, p);
initialize_sort_map (s);
list_elt = selected_list_element (s);
Bool available_p = (hack_number >= 0
? s->hacks_available_p [hack_number]
: True);
+ Bool nothing_p = (s->total_available < 5);
+
#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)
+ ? (available_p ? 1 :
+ nothing_p ? 3 : 2)
: 0));
#else /* !HAVE_GTK2 */
if (s->running_preview_error_p)
close (out); /* don't need this one */
*buf = 0;
- fgets (buf, sizeof(buf)-1, f);
+ if (!fgets (buf, sizeof(buf)-1, f))
+ *buf = 0;
fclose (f);
/* Wait for the child to die. */
perror (buf);
}
}
- else if (s->debug_p)
- fprintf (stderr, "%s: killed pid %lu (%s)\n", blurb(),
- (unsigned long) s->running_preview_pid, ss);
+ else {
+ int endstatus;
+ waitpid(s->running_preview_pid, &endstatus, 0);
+ if (s->debug_p)
+ fprintf (stderr, "%s: killed pid %lu (%s)\n", blurb(),
+ (unsigned long) s->running_preview_pid, ss);
+ }
free (ss);
s->running_preview_pid = 0;
the .ad file... */
#endif
+STFU
static char *defaults[] = {
#include "XScreenSaver_ad.h"
0
hack_environment (s); /* must be before initialize_sort_map() */
- load_init_file (p);
+ load_init_file (dpy, p);
initialize_sort_map (s);
/* Now that Xt has been initialized, and the resources have been read,
/* Issue any warnings about the running xscreensaver daemon. */
- the_network_is_not_the_computer (s);
+ if (! s->debug_p)
+ the_network_is_not_the_computer (s);
/* Run the Gtk event loop, and not the Xt event loop. This means that
gtk_timeout_add (500, delayed_scroll_kludge, s);
-#if 0
+#if 1
/* Load every configurator in turn, to scan them for errors all at once. */
- {
- int i;
- for (i = 0; i < p->screenhacks_count; i++)
- {
- screenhack *hack = p->screenhacks[i];
- conf_data *d = load_configurator (hack->command, False);
- if (d) free_conf_data (d);
- }
- }
+ if (s->debug_p)
+ {
+ int i;
+ for (i = 0; i < p->screenhacks_count; i++)
+ {
+ screenhack *hack = p->screenhacks[i];
+ conf_data *d = load_configurator (hack->command, s->debug_p);
+ if (d) free_conf_data (d);
+ }
+ }
#endif