http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / blitspin.c
index debdbaea58a5bf0328644d3b30a96dcb432597b2..1eebcb820f957747ce22215dfa2fda5e1e099b67 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1992-1997, 2003 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 "screenhack.h"
+#include "xpm-pixmap.h"
 #include <stdio.h>
 
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-#  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
-
-#include <X11/Xmu/Drawing.h>
-
-#include "default.xbm"
+#include "images/som.xbm"
 
 static Display *dpy;
 static Window window;
@@ -49,7 +41,7 @@ static Pixmap bitmap;
 static int depth;
 static unsigned int fg, bg;
 
-static void rotate(), init (), display ();
+static void display (Pixmap);
 
 #define copy_all_to(from, xoff, yoff, to, gc)          \
   XCopyArea (dpy, (from), (to), (gc), 0, 0,            \
@@ -60,7 +52,7 @@ static void rotate(), init (), display ();
             size-(xoff), size-(yoff), 0, 0)
 
 static void
-rotate ()
+rotate (void)
 {
   int qwad; /* fuckin' C, man... who needs namespaces? */
   XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
@@ -87,72 +79,58 @@ rotate ()
     }
 }
 
-static void
-read_bitmap (bitmap_name, widthP, heightP)
-     char *bitmap_name;
-     int *widthP, *heightP;
+static Pixmap
+read_screen (Display *dpy, Window window, int *widthP, int *heightP)
 {
-#ifdef HAVE_XPM
-  XpmAttributes xpmattrs;
-  int result;
-  xpmattrs.valuemask = 0;
-  bitmap = 0;
-  result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0,
-                               &xpmattrs);
-  switch (result)
-    {
-    case XpmColorError:
-      fprintf (stderr, "%s: warning: xpm color substitution performed\n",
-              progname);
-      /* fall through */
-    case XpmSuccess:
-      *widthP = xpmattrs.width;
-      *heightP = xpmattrs.height;
-      break;
-    case XpmFileInvalid:
-    case XpmOpenFailed:
-      bitmap = 0;
-      break;
-    case XpmColorFailed:
-      fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
-      exit (-1);
-    case XpmNoMemory:
-      fprintf (stderr, "%s: xpm: out of memory\n", progname);
-      exit (-1);
-    default:
-      fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
-      exit (-1);
-    }
-  if (! bitmap)
-#endif
-    {
-      int xh, yh;
-      Pixmap b2;
-      bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
-                                   0, 0, widthP, heightP, &xh, &yh);
-      if (! bitmap)
-       {
-         fprintf (stderr, "%s: couldn't find bitmap %s\n", progname,
-                  bitmap_name);
-         exit (1);
-       }
-      b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP,
-                                     depth, fg, bg);
-      XFreePixmap (dpy, bitmap);
-      bitmap = b2;
-    }
+  Pixmap p;
+  XWindowAttributes xgwa;
+  XGCValues gcv;
+  GC gc;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  *widthP = xgwa.width;
+  *heightP = xgwa.height;
+
+  p = XCreatePixmap(dpy, window, *widthP, *heightP, xgwa.depth);
+  gcv.function = GXcopy;
+  gc = XCreateGC (dpy, window, GCFunction, &gcv);
+
+  load_random_image (xgwa.screen, window, p, NULL);
+
+  /* Reset the window's background color... */
+  XSetWindowBackground (dpy, window,
+                       get_pixel_resource ("background", "Background",
+                                           dpy, xgwa.colormap));
+  XCopyArea (dpy, p, window, gc, 0, 0, *widthP, *heightP, 0, 0);
+  XFreeGC (dpy, gc);
+
+  return p;
+}
+
+
+static int 
+to_pow2(int n, Bool up)
+{
+  /* sizeof(Dimension) == 2. */
+  int powers_of_2[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+                       2048, 4096, 8192, 16384, 32768, 65536 };
+  int i = 0;
+  if (n > 65536) size = 65536;
+  while (n >= powers_of_2[i]) i++;
+  if (n == powers_of_2[i-1])
+    return n;
+  else
+    return powers_of_2[up ? i : i-1];
 }
 
 static void
-init ()
+init (void)
 {
   XWindowAttributes xgwa;
   Colormap cmap;
   XGCValues gcv;
   int width, height;
-  unsigned int real_size;
   char *bitmap_name;
-  int i;
+  Bool scale_up;
 
   XGetWindowAttributes (dpy, window, &xgwa);
   cmap = xgwa.colormap;
@@ -170,24 +148,34 @@ init ()
 
   if (!strcmp (bitmap_name, "(default)"))
     {
-      width = logo_width;
-      height = logo_height;
-      bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits,
+      width = som_width;
+      height = som_height;
+      bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) som_bits,
                                            width, height, fg, bg, depth);
+      scale_up = True; /* definitely. */
+    }
+  else if (!strcmp (bitmap_name, "(screen)"))
+    {
+      bitmap = read_screen (dpy, window, &width, &height);
+      scale_up = True; /* maybe? */
     }
   else
     {
-      read_bitmap (bitmap_name, &width, &height);
+      bitmap = xpm_file_to_pixmap (dpy, window, bitmap_name,
+                                   &width, &height, 0);
+      scale_up = True; /* probably? */
     }
 
-  real_size = (width > height) ? width : height;
+  size = (width < height) ? height : width;    /* make it square */
+  size = to_pow2(size, scale_up);              /* round up to power of 2 */
+  {                                            /* don't exceed screen size */
+    int s = XScreenNumberOfScreen(xgwa.screen);
+    int w = to_pow2(XDisplayWidth(dpy, s), False);
+    int h = to_pow2(XDisplayHeight(dpy, s), False);
+    if (size > w) size = w;
+    if (size > h) size = h;
+  }
 
-  size = real_size;
-  /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
-  for (i = 31; i > 0; i--)
-    if (size & (1<<i)) break;
-  if (size & (~(1<<i)))
-    size = (size>>i)<<(i+1);
   self = XCreatePixmap (dpy, window, size, size, depth);
   temp = XCreatePixmap (dpy, window, size, size, depth);
   mask = XCreatePixmap (dpy, window, size, size, depth);
@@ -207,11 +195,15 @@ init ()
 
   XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
             (size - width)>>1, (size - height)>>1);
+  XFreePixmap(dpy, bitmap);
+
+  display (self);
+  XSync(dpy, False);
+  screenhack_handle_events (dpy);
 }
 
 static void
-display (pixmap)
-     Pixmap pixmap;
+display (Pixmap pixmap)
 {
   XWindowAttributes xgwa;
   static int last_w = 0, last_h = 0;
@@ -222,12 +214,10 @@ display (pixmap)
       last_w = xgwa.width;
       last_h = xgwa.height;
     }
-#ifdef HAVE_XPM
   if (depth != 1)
     XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
               (xgwa.width-size)>>1, (xgwa.height-size)>>1);
   else
-#endif
     XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
                (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
 /*
@@ -235,39 +225,42 @@ display (pixmap)
                  ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
                  size+2, size+2);
 */
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
 }
 
 \f
 char *progclass = "BlitSpin";
 
 char *defaults [] = {
-  "BlitSpin.background:        black",         /* to placate SGI */
-  "BlitSpin.foreground:        white",
+  ".background:        black",
+  ".foreground:        white",
   "*delay:     500000",
   "*delay2:    500000",
   "*bitmap:    (default)",
+  "*geometry:  512x512",
   0
 };
 
 XrmOptionDescRec options [] = {
   { "-delay",          ".delay",       XrmoptionSepArg, 0 },
   { "-delay2",         ".delay2",      XrmoptionSepArg, 0 },
-  { "-bitmap",         ".bitmap",      XrmoptionSepArg, 0 }
+  { "-bitmap",         ".bitmap",      XrmoptionSepArg, 0 },
+  { "-grab-screen",    ".bitmap",      XrmoptionNoArg, "(screen)" },
+  { 0, 0, 0, 0 }
 };
-int options_size = (sizeof (options) / sizeof (options[0]));
 
 void
-screenhack (d, w)
-     Display *d;
-     Window w;
+screenhack (Display *d, Window w)
 {
   dpy = d;
   window = w;
   init ();
+  if (delay2) usleep (delay2 * 2);
   while (1)
     {
       rotate ();
+      screenhack_handle_events (d);
       if (delay2) usleep (delay2);
     }
 }