From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / driver / demo-Gtk.c
index 28d2925bc7c69ec4e1b062591f5b928f303811a3..f5c483965a3a8ead6947abc473d9ea4a823f1c29 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2008 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2016 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 "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 <stdio.h>
@@ -535,7 +530,7 @@ static void warning_dialog_killk_cb (GtkWidget *widget, gpointer user_data)
 
 typedef enum { D_NONE, D_LAUNCH, D_GNOME, D_KDE } dialog_button;
 
-static void
+static Bool
 warning_dialog (GtkWidget *parent, const char *message,
                 dialog_button button_type, int center)
 {
@@ -555,7 +550,8 @@ warning_dialog (GtkWidget *parent, const char *message,
       !GET_WINDOW (parent)) /* too early to pop up transient dialogs */
     {
       fprintf (stderr, "%s: too early for dialog?\n", progname);
-      return;
+      free(msg);
+      return False;
     }
 
   head = msg;
@@ -680,6 +676,7 @@ warning_dialog (GtkWidget *parent, const char *message,
 #endif /* !HAVE_GTK2 */
 
   free (msg);
+  return True;
 }
 
 
@@ -801,23 +798,30 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
 {
   char msg [2048];
   char *vers = strdup (screensaver_id + 4);
-  char *s;
+  char *s, *s2;
   char copy[1024];
-  char *desc = _("For updates, check http://www.jwz.org/xscreensaver/");
+  char year[5];
+  char *desc = _("For updates, check https://www.jwz.org/xscreensaver/");
 
   s = strchr (vers, ',');
   *s = 0;
   s += 2;
 
+  s2 = vers;
+  s2 = strrchr (vers, '-');
+  s2++;
+  strncpy (year, s2, 4);
+  year[4] = 0;
+
   /* 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-2008 %s"), s);
+  sprintf(copy, ("Copyright \xC2\xA9 1991-%s %s"), year, s);
 #else  /* !HAVE_GTK2 */
-  sprintf(copy, ("Copyright \251 1991-2008 %s"), s);
+  sprintf(copy, ("Copyright \251 1991-%s %s"), year, s);
 #endif /* !HAVE_GTK2 */
 
   sprintf (msg, "%s\n\n%s", copy, desc);
@@ -1411,19 +1415,32 @@ normalize_directory (const char *path)
             {
               s0--;
               s += 3;
-              strcpy (s0, s);
+              /* strcpy (s0, s); */
+              memmove(s0, s, strlen(s) + 1);
               s = s0-1;
             }
         }
-      else if (*s == '/' && !strncmp (s, "/./", 3))    /* delete "/./" */
-        strcpy (s, s+2), s--;
+      else if (*s == '/' && !strncmp (s, "/./", 3)) {  /* delete "/./" */
+        /* strcpy (s, s+2), s--; */
+        memmove(s, s+2, strlen(s+2) + 1);
+        s--;
+       }
       else if (*s == '/' && !strncmp (s, "/.\000", 3)) /* delete "/.$" */
         *s = 0, s--;
     }
 
-  for (s = p2; s && *s; s++)           /* normalize consecutive slashes */
-    while (s[0] == '/' && s[1] == '/')
-      strcpy (s, s+1);
+  /*
+    Normalize consecutive slashes.
+    Ignore doubled slashes after ":" to avoid mangling URLs.
+  */
+
+  for (s = p2; s && *s; s++){
+    if (*s == ':') continue;
+    if (!s[1] || !s[2]) continue;
+    while (s[1] == '/' && s[2] == '/')
+      /* strcpy (s+1, s+2); */
+      memmove (s+1, s+2, strlen(s+2) + 1);
+  }
 
   /* and strip trailing whitespace for good measure. */
   L = strlen(p2);
@@ -1485,6 +1502,7 @@ flush_dialog_changes_and_save (state *s)
   GList *kids = gtk_container_children (GTK_CONTAINER (list_widget));
   int i;
 #endif /* !HAVE_GTK2 */
+  static Bool already_warned_about_missing_image_directory = False; /* very long name... */
 
   Bool changed = False;
   GtkWidget *w;
@@ -1539,14 +1557,15 @@ flush_dialog_changes_and_save (state *s)
 
 # define TEXT(FIELD,NAME) \
     w = name_to_widget (s, (NAME)); \
-    (FIELD) = (char *) gtk_entry_get_text (GTK_ENTRY (w))
+    (FIELD) = (char *) g_strdup(gtk_entry_get_text (GTK_ENTRY (w)))
 
   MINUTES  (&p2->timeout,         "timeout_spinbutton");
   MINUTES  (&p2->cycle,           "cycle_spinbutton");
   CHECKBOX (p2->lock_p,           "lock_button");
   MINUTES  (&p2->lock_timeout,    "lock_spinbutton");
 
-  CHECKBOX (p2->dpms_enabled_p,  "dpms_button");
+  CHECKBOX (p2->dpms_enabled_p,   "dpms_button");
+  CHECKBOX (p2->dpms_quickoff_p,  "dpms_quickoff_button");
   MINUTES  (&p2->dpms_standby,    "dpms_standby_spinbutton");
   MINUTES  (&p2->dpms_suspend,    "dpms_suspend_spinbutton");
   MINUTES  (&p2->dpms_off,        "dpms_off_spinbutton");
@@ -1587,16 +1606,28 @@ flush_dialog_changes_and_save (state *s)
 # undef PATHNAME
 # undef TEXT
 
-  /* Warn if the image directory doesn't exist.
+  /* Warn if the image directory doesn't exist, when:
+     - not being warned before
+     - image directory is changed and the directory doesn't exist
+     - image directory does not begin with http://
    */
   if (p2->image_directory &&
       *p2->image_directory &&
-      !directory_p (p2->image_directory))
+      !directory_p (p2->image_directory) &&
+       strncmp(p2->image_directory, "http://", 6) &&
+        ( !already_warned_about_missing_image_directory ||
+          ( p->image_directory &&
+            *p->image_directory &&
+            strcmp(p->image_directory, p2->image_directory)
+          )
+        )
+      )
     {
       char b[255];
-      sprintf (b, "Error:\n\n" "Directory does not exist: \"%s\"\n",
+      sprintf (b, "Warning:\n\n" "Directory does not exist: \"%s\"\n",
                p2->image_directory);
-      warning_dialog (s->toplevel_widget, b, D_NONE, 100);
+      if (warning_dialog (s->toplevel_widget, b, D_NONE, 100))
+        already_warned_about_missing_image_directory = True;
     }
 
 
@@ -1635,10 +1666,11 @@ flush_dialog_changes_and_save (state *s)
   COPY(lock_p,         "lock_p");
   COPY(lock_timeout,   "lock_timeout");
 
-  COPY(dpms_enabled_p, "dpms_enabled_p");
-  COPY(dpms_standby,   "dpms_standby");
-  COPY(dpms_suspend,   "dpms_suspend");
-  COPY(dpms_off,       "dpms_off");
+  COPY(dpms_enabled_p,  "dpms_enabled_p");
+  COPY(dpms_quickoff_p, "dpms_quickoff_enabled_p");
+  COPY(dpms_standby,    "dpms_standby");
+  COPY(dpms_suspend,    "dpms_suspend");
+  COPY(dpms_off,        "dpms_off");
 
 #if 0
   COPY(verbose_p,        "verbose_p");
@@ -1686,7 +1718,7 @@ flush_dialog_changes_and_save (state *s)
     {
       Display *dpy = GDK_DISPLAY();
       Bool enabled_p = (p->dpms_enabled_p && p->mode != DONT_BLANK);
-      sync_server_dpms_settings (dpy, enabled_p,
+      sync_server_dpms_settings (dpy, enabled_p, p->dpms_quickoff_p,
                                  p->dpms_standby / 1000,
                                  p->dpms_suspend / 1000,
                                  p->dpms_off / 1000,
@@ -2052,7 +2084,8 @@ store_image_directory (GtkWidget *button, gpointer user_data)
   if (p->image_directory && !strcmp(p->image_directory, path))
     return;  /* no change */
 
-  if (!directory_p (path))
+  /* No warning for URLs. */
+  if ((!directory_p (path)) && strncmp(path, "http://", 6))
     {
       char b[255];
       sprintf (b, _("Error:\n\n" "Directory does not exist: \"%s\"\n"), path);
@@ -2783,6 +2816,7 @@ populate_prefs_page (state *s)
   TOGGLE_ACTIVE ("splash_button",     p->splash_p);
 #endif
   TOGGLE_ACTIVE ("dpms_button",       p->dpms_enabled_p);
+  TOGGLE_ACTIVE ("dpms_quickoff_button", p->dpms_quickoff_p);
   TOGGLE_ACTIVE ("grab_desk_button",  p->grab_desktop_p);
   TOGGLE_ACTIVE ("grab_video_button", p->grab_video_p);
   TOGGLE_ACTIVE ("grab_image_button", p->random_image_p);
@@ -2886,8 +2920,11 @@ populate_prefs_page (state *s)
 
     /* DPMS
      */
+dpms_supported=1;
     SENSITIZE ("dpms_frame",              dpms_supported);
     SENSITIZE ("dpms_button",             dpms_supported);
+    SENSITIZE ("dpms_quickoff_button",    dpms_supported);
+
     SENSITIZE ("dpms_standby_label",      dpms_supported && p->dpms_enabled_p);
     SENSITIZE ("dpms_standby_mlabel",     dpms_supported && p->dpms_enabled_p);
     SENSITIZE ("dpms_standby_spinbutton", dpms_supported && p->dpms_enabled_p);
@@ -4295,9 +4332,8 @@ static void
 init_icon (GdkWindow *window)
 {
   GdkBitmap *mask = 0;
-  GdkColor transp;
   GdkPixmap *pixmap =
-    gdk_pixmap_create_from_xpm_d (window, &mask, &transp,
+    gdk_pixmap_create_from_xpm_d (window, &mask, 0,
                                   (gchar **) logo_50_xpm);
   if (pixmap)
     gdk_window_set_icon (window, 0, pixmap, mask);
@@ -4680,7 +4716,7 @@ delayed_scroll_kludge (gpointer data)
 
 #ifdef HAVE_GTK2
 
-GtkWidget *
+static GtkWidget *
 create_xscreensaver_demo (void)
 {
   GtkWidget *nb;
@@ -4691,7 +4727,7 @@ create_xscreensaver_demo (void)
   return name_to_widget (global_state_kludge, "xscreensaver_demo");
 }
 
-GtkWidget *
+static GtkWidget *
 create_xscreensaver_settings_dialog (void)
 {
   GtkWidget *w, *box;
@@ -5256,6 +5292,20 @@ main (int argc, char **argv)
     the_network_is_not_the_computer (s);
 
 
+  if (decrepit_p())
+    warning_dialog (s->toplevel_widget,
+      _("Warning:\n\n"
+        "This version of xscreensaver is VERY OLD!\n"
+        "Please upgrade!\n"
+        "\n"
+        "https://www.jwz.org/xscreensaver/\n"
+        "\n"
+        "(If this is the latest version that your distro ships, then\n"
+        "your distro is doing you a disservice. Build from source.)\n"
+        ),
+      D_NONE, 7);
+
+
   /* Run the Gtk event loop, and not the Xt event loop.  This means that
      if there were Xt timers or fds registered, they would never get serviced,
      and if there were any Xt widgets, they would never have events delivered.