ftp://ftp.sunet.se/pub/vendor/sco/skunkware/osr5/x11/savers/xscreensaver/xscreensaver...
[xscreensaver] / hacks / jigsaw.c
diff --git a/hacks/jigsaw.c b/hacks/jigsaw.c
deleted file mode 100644 (file)
index 246c9da..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-/* xscreensaver, Copyright (c) 1997, 1998 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
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- */
-
-/*
-  TODO:
-
-    =  Rather than just flickering the pieces before swapping them,
-       show them lifting up and moving to their new positions.
-       The path on which they move shouldn't be a straight line;
-       try to avoid having them cross each other by moving them in
-       oppositely-positioned arcs.
-
-    =  Rotate the pieces as well, so that we can swap the corner
-       and edge pieces with each other.
-
-    =  The shapes of the piece bitmaps still aren't quite right.
-       They should line up with no overlap.  They don't...
-    
-    =  Have it drop all pieces to the "floor" then pick them up to
-       reassemble the picture.
-
-    =  As a joke, maybe sometimes have one piece that doesn't fit?
-       Or lose a piece?
- */
-
-#include "screenhack.h"
-
-#define DEBUG
-
-#include "images/jigsaw/jigsaw_a_h.xbm"
-#include "images/jigsaw/jigsaw_a_n_h.xbm"
-#include "images/jigsaw/jigsaw_a_ne_h.xbm"
-#include "images/jigsaw/jigsaw_a_e_h.xbm"
-#include "images/jigsaw/jigsaw_a_se_h.xbm"
-#include "images/jigsaw/jigsaw_a_s_h.xbm"
-#include "images/jigsaw/jigsaw_a_sw_h.xbm"
-#include "images/jigsaw/jigsaw_a_w_h.xbm"
-#include "images/jigsaw/jigsaw_a_nw_h.xbm"
-
-#include "images/jigsaw/jigsaw_b_h.xbm"
-#include "images/jigsaw/jigsaw_b_n_h.xbm"
-#include "images/jigsaw/jigsaw_b_ne_h.xbm"
-#include "images/jigsaw/jigsaw_b_e_h.xbm"
-#include "images/jigsaw/jigsaw_b_se_h.xbm"
-#include "images/jigsaw/jigsaw_b_s_h.xbm"
-#include "images/jigsaw/jigsaw_b_sw_h.xbm"
-#include "images/jigsaw/jigsaw_b_w_h.xbm"
-#include "images/jigsaw/jigsaw_b_nw_h.xbm"
-
-#include "images/jigsaw/jigsaw_a_f.xbm"
-#include "images/jigsaw/jigsaw_a_n_f.xbm"
-#include "images/jigsaw/jigsaw_a_ne_f.xbm"
-#include "images/jigsaw/jigsaw_a_e_f.xbm"
-#include "images/jigsaw/jigsaw_a_se_f.xbm"
-#include "images/jigsaw/jigsaw_a_s_f.xbm"
-#include "images/jigsaw/jigsaw_a_sw_f.xbm"
-#include "images/jigsaw/jigsaw_a_w_f.xbm"
-#include "images/jigsaw/jigsaw_a_nw_f.xbm"
-
-#include "images/jigsaw/jigsaw_b_f.xbm"
-#include "images/jigsaw/jigsaw_b_n_f.xbm"
-#include "images/jigsaw/jigsaw_b_ne_f.xbm"
-#include "images/jigsaw/jigsaw_b_e_f.xbm"
-#include "images/jigsaw/jigsaw_b_se_f.xbm"
-#include "images/jigsaw/jigsaw_b_s_f.xbm"
-#include "images/jigsaw/jigsaw_b_sw_f.xbm"
-#include "images/jigsaw/jigsaw_b_w_f.xbm"
-#include "images/jigsaw/jigsaw_b_nw_f.xbm"
-
-#define GRID_WIDTH  66
-#define GRID_HEIGHT 66
-
-#define CENTER   0
-#define NORTH    1
-#define NORTHEAST 2
-#define EAST     3
-#define SOUTHEAST 4
-#define SOUTH    5
-#define SOUTHWEST 6
-#define WEST     7
-#define NORTHWEST 8
-
-struct piece {
-  int width, height;
-  int x, y;
-  Pixmap pixmap;
-};
-
-struct set {
-  struct piece pieces[9];
-};
-
-#define PIECE_A_HOLLOW 0
-#define PIECE_A_FILLED 1
-#define PIECE_B_HOLLOW 2
-#define PIECE_B_FILLED 3
-
-static struct set all_pieces[4];
-
-static void
-init_images(Display *dpy, Window window)
-{
-# define LOAD_PIECE(PIECE,NAME)                                        \
-    PIECE.x = jigsaw_##NAME##_x_hot;                           \
-    PIECE.y = jigsaw_##NAME##_y_hot;                           \
-    PIECE.pixmap =                                             \
-    XCreatePixmapFromBitmapData(dpy, window,                   \
-                               (char *) jigsaw_##NAME##_bits,  \
-                               jigsaw_##NAME##_width,          \
-                               jigsaw_##NAME##_height,         \
-                               1, 0, 1)
-
-# define LOAD_PIECES(SET,PREFIX,SUFFIX)                                \
-    LOAD_PIECE(SET.pieces[CENTER],    PREFIX##_##SUFFIX);      \
-    LOAD_PIECE(SET.pieces[NORTH],     PREFIX##_n_##SUFFIX);    \
-    LOAD_PIECE(SET.pieces[NORTHEAST], PREFIX##_ne_##SUFFIX);   \
-    LOAD_PIECE(SET.pieces[EAST],      PREFIX##_e_##SUFFIX);    \
-    LOAD_PIECE(SET.pieces[SOUTHEAST], PREFIX##_se_##SUFFIX);   \
-    LOAD_PIECE(SET.pieces[SOUTH],     PREFIX##_s_##SUFFIX);    \
-    LOAD_PIECE(SET.pieces[SOUTHWEST], PREFIX##_sw_##SUFFIX);   \
-    LOAD_PIECE(SET.pieces[WEST],      PREFIX##_w_##SUFFIX);    \
-    LOAD_PIECE(SET.pieces[NORTHWEST], PREFIX##_nw_##SUFFIX)
-
-  LOAD_PIECES(all_pieces[PIECE_A_HOLLOW],a,h);
-  LOAD_PIECES(all_pieces[PIECE_A_FILLED],a,f);
-  LOAD_PIECES(all_pieces[PIECE_B_HOLLOW],b,h);
-  LOAD_PIECES(all_pieces[PIECE_B_FILLED],b,f);
-
-# undef LOAD_PIECE
-# undef LOAD_PIECES
-}
-
-static Pixmap
-read_screen (Display *dpy, Window window, int *widthP, int *heightP)
-{
-  Pixmap p;
-  XWindowAttributes xgwa;
-  XGCValues gcv;
-  GC gc;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  *widthP = xgwa.width;
-  *heightP = xgwa.height;
-
-  XClearWindow(dpy, window);
-  grab_screen_image(xgwa.screen, window);
-  p = XCreatePixmap(dpy, window, *widthP, *heightP, xgwa.depth);
-  gcv.function = GXcopy;
-  gc = XCreateGC (dpy, window, GCFunction, &gcv);
-  XCopyArea (dpy, window, p, gc, 0, 0, *widthP, *heightP, 0, 0);
-
-  XFreeGC (dpy, gc);
-
-  return p;
-}
-
-
-static int width, height;
-static int x_border, y_border;
-static Pixmap source;
-static GC gc;
-static Bool tweak;
-static int fg, bg;
-static XPoint *state = 0;
-
-static void
-jigsaw_init(Display *dpy, Window window)
-{
-  XWindowAttributes xgwa;
-  int x, y;
-  XGCValues gcv;
-  Colormap cmap;
-  int source_w, source_h;
-
-  tweak = random()&1;
-
-  source = read_screen (dpy, window, &source_w, &source_h);
-
-  XGetWindowAttributes (dpy, window, &xgwa);
-  cmap = xgwa.colormap;
-  width  = xgwa.width  / GRID_WIDTH;
-  height = xgwa.height / GRID_HEIGHT;
-  x_border = (xgwa.width  - (width  * GRID_WIDTH)) / 2;
-  y_border = (xgwa.height - (height * GRID_WIDTH)) / 2;
-
-  if (!state)
-    state = (XPoint *) malloc(width * height * sizeof(XPoint));
-  gc = XCreateGC (dpy, window, 0, &gcv);
-
-  {
-    XColor fgc, bgc;
-    char *fgs = get_string_resource("foreground", "Foreground");
-    char *bgs = get_string_resource("background", "Background");
-    Bool fg_ok, bg_ok;
-    if (!XParseColor (dpy, cmap, fgs, &fgc))
-      XParseColor (dpy, cmap, "gray", &fgc);
-    if (!XParseColor (dpy, cmap, bgs, &bgc))
-      XParseColor (dpy, cmap, "black", &bgc);
-
-    fg_ok = XAllocColor (dpy, cmap, &fgc);
-    bg_ok = XAllocColor (dpy, cmap, &bgc);
-
-    /* If we weren't able to allocate the two colors we want from the
-       colormap (which is likely if the screen has been grabbed on an
-       8-bit SGI visual -- don't ask) then just go through the map
-       and find the closest color to the ones we wanted, and use those
-       pixels without actually allocating them.
-     */
-    if (fg_ok)
-      fg = fgc.pixel;
-    else
-      fg = 0;
-
-    if (bg_ok)
-      bg = bgc.pixel;
-    else
-      bg = 1;
-
-    if (!fg_ok || bg_ok)
-      {
-       int i;
-       unsigned long fgd = ~0;
-       unsigned long bgd = ~0;
-       int max = visual_cells (xgwa.screen, xgwa.visual);
-       XColor *all = (XColor *) calloc(sizeof (*all), max);
-       for (i = 0; i < max; i++)
-         {
-           all[i].flags = DoRed|DoGreen|DoBlue;
-           all[i].pixel = i;
-         }
-       XQueryColors (dpy, cmap, all, max);
-       for(i = 0; i < max; i++)
-         {
-           long rd, gd, bd;
-           unsigned long d;
-           if (!fg_ok)
-             {
-               rd = (all[i].red   >> 8) - (fgc.red   >> 8);
-               gd = (all[i].green >> 8) - (fgc.green >> 8);
-               bd = (all[i].blue  >> 8) - (fgc.blue  >> 8);
-               if (rd < 0) rd = -rd;
-               if (gd < 0) gd = -gd;
-               if (bd < 0) bd = -bd;
-               d = (rd << 1) + (gd << 2) + bd;
-               if (d < fgd)
-                 {
-                   fgd = d;
-                   fg = all[i].pixel;
-                   if (d == 0)
-                     fg_ok = True;
-                 }
-             }
-
-           if (!bg_ok)
-             {
-               rd = (all[i].red   >> 8) - (bgc.red   >> 8);
-               gd = (all[i].green >> 8) - (bgc.green >> 8);
-               bd = (all[i].blue  >> 8) - (bgc.blue  >> 8);
-               if (rd < 0) rd = -rd;
-               if (gd < 0) gd = -gd;
-               if (bd < 0) bd = -bd;
-               d = (rd << 1) + (gd << 2) + bd;
-               if (d < bgd)
-                 {
-                   bgd = d;
-                   bg = all[i].pixel;
-                   if (d == 0)
-                     bg_ok = True;
-                 }
-             }
-
-           if (fg_ok && bg_ok)
-             break;
-         }
-       XFree(all);
-      }
-  }
-
-  /* Reset the window's background color... */
-  XSetWindowBackground (dpy, window, bg);
-  XClearWindow(dpy, window);
-
-  for (y = 0; y < height; y++)
-    for (x = 0; x < width; x++)
-      {
-       state[y * width + x].x = x;
-       state[y * width + x].y = y;
-      }
-}
-
-
-static void
-get_piece(int x, int y, struct piece **hollow, struct piece **filled)
-{
-  int p;
-  Bool which = (x & 1) == (y & 1);
-
-  if      (x == 0       && y == 0)       p = NORTHWEST;
-  else if (x == width-1 && y == 0)       p = NORTHEAST;
-  else if (x == width-1 && y == height-1) p = SOUTHEAST;
-  else if (x == 0       && y == height-1) p = SOUTHWEST;
-  else if (y == 0)                       p = NORTH;
-  else if (x == width-1)                 p = EAST;
-  else if (y == height-1)                p = SOUTH;
-  else if (x == 0)                       p = WEST;
-  else                                   p = CENTER;
-
-  if (tweak) which = !which;
-  if (hollow)
-    *hollow = (which
-              ? &all_pieces[PIECE_A_HOLLOW].pieces[p]
-              : &all_pieces[PIECE_B_HOLLOW].pieces[p]);
-  if (filled)
-    *filled = (which
-              ? &all_pieces[PIECE_A_FILLED].pieces[p]
-              : &all_pieces[PIECE_B_FILLED].pieces[p]);
-}
-
-
-static void
-draw_piece(Display *dpy, Window window, int x, int y, int clear_p)
-{
-  struct piece *hollow, *filled;
-  int from_x = state[y * width + x].x;
-  int from_y = state[y * width + x].y;
-
-  get_piece(x, y, &hollow, &filled);
-         
-  XSetClipMask(dpy, gc, filled->pixmap);
-  XSetClipOrigin(dpy, gc,
-                x_border + (x * GRID_WIDTH) - filled->x - 1,
-                y_border + (y * GRID_WIDTH) - filled->y - 1);
-
-  if (clear_p)
-    {
-      XSetForeground(dpy, gc, bg);
-      XFillRectangle(dpy, window, gc,
-                    x_border + (x * GRID_WIDTH)  - GRID_WIDTH/2,
-                    y_border + (y * GRID_HEIGHT) - GRID_HEIGHT/2,
-                    GRID_WIDTH*2, GRID_HEIGHT*2);
-    }
-  else
-    XCopyArea(dpy, source, window, gc,
-             x_border + (from_x * GRID_WIDTH)  - GRID_WIDTH/2,
-             y_border + (from_y * GRID_HEIGHT) - GRID_HEIGHT/2,
-             GRID_WIDTH*2, GRID_HEIGHT*2,
-             x_border + (x * GRID_WIDTH)  - GRID_WIDTH/2,
-             y_border + (y * GRID_HEIGHT) - GRID_HEIGHT/2);
-
-  if (clear_p > 1)
-    return;
-
-  XSetForeground(dpy, gc, fg);
-  XSetClipMask(dpy, gc, hollow->pixmap);
-  XSetClipOrigin(dpy, gc,
-                x_border + (x * GRID_WIDTH) - hollow->x - 1,
-                y_border + (y * GRID_WIDTH) - hollow->y - 1);
-  XFillRectangle(dpy, window, gc,
-                x_border + (x * GRID_WIDTH)  - GRID_WIDTH/2,
-                y_border + (y * GRID_HEIGHT) - GRID_HEIGHT/2,
-                GRID_WIDTH*2, GRID_HEIGHT*2);
-
-  if (clear_p)
-    {
-      /* If the pieces lined up right, we could do this by just not drawing
-        the outline -- but that doesn't look right, since it eats the outlines
-        of the adjascent pieces.  So draw the outline, then chop off the outer
-        edge if this is a border piece.
-       */
-      XSetForeground(dpy, gc, bg);
-      if (x == 0)
-       XFillRectangle(dpy, window, gc,
-                      x_border - 2,
-                      y_border + (y * GRID_HEIGHT),
-                      3, GRID_HEIGHT);
-      else if (x == width-1)
-       XFillRectangle(dpy, window, gc,
-                      x_border + ((x+1) * GRID_WIDTH) - 2,
-                      y_border + (y * GRID_HEIGHT),
-                      3, GRID_HEIGHT);
-
-      if (y == 0)
-       XFillRectangle(dpy, window, gc,
-                      x_border + (x * GRID_WIDTH),
-                      y_border - 2,
-                      GRID_WIDTH, 3);
-      else if (y == height-1)
-       XFillRectangle(dpy, window, gc,
-                      x_border + (x * GRID_WIDTH),
-                      y_border + ((y+1) * GRID_HEIGHT) - 2,
-                      GRID_WIDTH, 3);
-    }
-}
-
-
-static void
-swap_pieces(Display *dpy, Window window,
-           int src_x, int src_y, int dst_x, int dst_y,
-           Bool draw_p)
-{
-  XPoint swap;
-  int i;
-  if (draw_p)
-    for (i = 0; i < 3; i++)
-      {
-       draw_piece(dpy, window, src_x, src_y, 1);
-       draw_piece(dpy, window, dst_x, dst_y, 1);
-       XSync(dpy, False);
-       usleep(50000);
-       draw_piece(dpy, window, src_x, src_y, 0);
-       draw_piece(dpy, window, dst_x, dst_y, 0);
-       XSync(dpy, False);
-       usleep(50000);
-      }
-
-  swap = state[src_y * width + src_x];
-  state[src_y * width + src_x] = state[dst_y * width + dst_x];
-  state[dst_y * width + dst_x] = swap;
-
-  if (draw_p)
-    {
-      draw_piece(dpy, window, src_x, src_y, 0);
-      draw_piece(dpy, window, dst_x, dst_y, 0);
-      XSync(dpy, False);
-    }
-}
-
-
-static void
-shuffle(Display *dpy, Window window, Bool draw_p)
-{
-  struct piece *p1, *p2;
-  int src_x, src_y, dst_x = -1, dst_y = -1;
-
- AGAIN:
-  p1 = p2 = 0;
-  src_x = random() % width;
-  src_y = random() % height;
-
-  get_piece(src_x, src_y, &p1, 0);
-
-  /* Pick random coordinates until we find one that has the same kind of
-     piece as the first one we picked.  Note that it's possible for there
-     to be only one piece of a particular shape on the board (this commonly
-     happens with the corner pieces.)
-   */
-  while (p1 != p2)
-    {
-      dst_x = random() % width;
-      dst_y = random() % height;
-      get_piece(dst_x, dst_y, &p2, 0);
-    }
-
-  if (src_x == dst_x && src_y == dst_y)
-    goto AGAIN;
-
-  swap_pieces(dpy, window, src_x, src_y, dst_x, dst_y, draw_p);
-}
-
-
-static void
-shuffle_all(Display *dpy, Window window)
-{
-  int i = (width * height * 10);
-  while (i > 0)
-    {
-      shuffle(dpy, window, False);
-      i--;
-    }
-}
-
-static void
-unshuffle(Display *dpy, Window window)
-{
-  int i;
-  for (i = 0; i < width * height * 4; i++)
-    {
-      int x = random() % width;
-      int y = random() % height;
-      int x2 = state[y * width + x].x;
-      int y2 = state[y * width + x].y;
-      if (x != x2 || y != y2)
-       {
-         swap_pieces(dpy, window, x, y, x2, y2, True);
-         break;
-       }
-    }
-}
-
-static void
-clear_all(Display *dpy, Window window)
-{
-  int n = width * height;
-  while (n > 0)
-    {
-      int x = random() % width;
-      int y = random() % height;
-      XPoint *p = &state[y * width + x];
-      if (p->x == -1)
-       continue;
-      draw_piece(dpy, window, p->x, p->y, 2);
-      XSync(dpy, False);
-      usleep(1000);
-      p->x = p->y = -1;
-      n--;
-    }
-}
-
-static Bool
-done(void)
-{
-  int x, y;
-  for (y = 0; y < height; y++)
-    for (x = 0; x < width; x++)
-      {
-       int x2 = state[y * width + x].x;
-       int y2 = state[y * width + x].y;
-       if (x != x2 || y != y2)
-         return False;
-      }
-  return True;
-}
-
-
-\f
-char *progclass = "Jigsaw";
-
-char *defaults [] = {
-  ".background:                Black",
-  ".foreground:                Gray40",
-  "*delay:             70000",
-  "*delay2:            5",
-  0
-};
-
-XrmOptionDescRec options [] = {
-  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
-  { "-delay2",         ".delay2",              XrmoptionSepArg, 0 },
-  { 0, 0, 0, 0 }
-};
-
-void
-screenhack (Display *dpy, Window window)
-{
-  int delay = get_integer_resource("delay", "Integer");
-  int delay2 = get_integer_resource("delay2", "Integer");
-
-  init_images(dpy, window);
-
-  while (1)
-    {
-      int x, y;
-      jigsaw_init (dpy, window);
-      shuffle_all(dpy, window);
-
-      for (y = 0; y < height; y++)
-       for (x = 0; x < width; x++)
-         draw_piece(dpy, window, x, y, 0);
-
-      while (!done())
-       {
-         unshuffle(dpy, window);
-         XSync (dpy, False);
-          screenhack_handle_events (dpy);
-         if (delay) usleep (delay);
-       }
-
-      screenhack_handle_events (dpy);
-      if (delay2)
-       usleep (delay2 * 1000000);
-
-      clear_all(dpy, window);
-    }
-}