http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / noseguy.c
index 594d7462e3d3b961e5a1713a6fcceafe9fef4b89..f6502bef5621059f5214e5291c52bf0debcfd939 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1996, 1997, 1998, 2005
+/* xscreensaver, Copyright (c) 1992, 1996, 1997, 1998, 2005, 2006
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
 #include "xpm-pixmap.h"
 #include <stdio.h>
 
+#ifdef HAVE_COCOA
+# define HAVE_XPM
+#endif
+
 extern FILE *popen (const char *, const char *);
 extern int pclose (FILE *);
 
 #define font_height(font)              (font->ascent + font->descent)
-#define FONT_NAME                      "-*-times-*-*-*-*-18-*-*-*-*-*-*-*"
-
-static Display *dpy;
-static Window window;
-static int Width, Height;
-static GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
-static char *words;
-static char *get_words (void);
-static int x, y;
-static XFontStruct *font;
-static void walk (int dir);
-static void talk (int erase);
-static void talk_1 (void);
-static int think (void);
-static unsigned long interval;
-static unsigned long look (void); 
-static Pixmap left1, left2, right1, right2;
-static Pixmap left_front, right_front, front, down;
-
-static char *program, *orig_program, *filename, *text;
+
+
+struct state {
+  Display *dpy;
+  Window window;
+  int Width, Height;
+  GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
+  char *words;
+  int x, y;
+  XFontStruct *font;
+
+  unsigned long interval;
+  Pixmap left1, left2, right1, right2;
+  Pixmap left_front, right_front, front, down;
+
+  char *program, *orig_program;
+
+  int state;   /* indicates states: walking or getting passwd */
+  int first_time;
+
+  void (*next_fn) (struct state *);
+
+  int move_length, move_dir;
+
+  int      walk_lastdir;
+  int      walk_up;
+  Pixmap   walk_frame;
+
+  int X, Y, talking;
+
+  struct {
+    int x, y, width, height;
+  } s_rect;
+
+  char word_buf[BUFSIZ];
+};
+
+static char *get_words (struct state *);
+static void walk (struct state *, int dir);
+static void talk (struct state *, int erase);
+static void talk_1 (struct state *);
+static int think (struct state *);
+static unsigned long look (struct state *); 
 
 #define FROM_ARGV    1
 #define FROM_PROGRAM 2
@@ -51,9 +78,6 @@ static char *program, *orig_program, *filename, *text;
 
 #define IS_MOVING  1
 #define GET_PASSWD 2
-static int state;      /* indicates states: walking or getting passwd */
-
-static void (*next_fn) (void);
 
 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
 # include "images/noseguy/nose-f1.xpm"
@@ -76,24 +100,40 @@ static void (*next_fn) (void);
 #endif
 
 static void
-init_images (void)
+init_images (struct state *st)
 {
-  static Pixmap *images[] = {
-    &left1, &left2, &right1, &right2,
-    &left_front, &right_front, &front, &down
-  };
-  int i;
+  Pixmap *images[8];
 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
+  char **bits[8];
+#else
+  unsigned char *bits[8];
+#endif
+
+  int i = 0;
+  images[i++] = &st->left1;
+  images[i++] = &st->left2;
+  images[i++] = &st->right1;
+  images[i++] = &st->right2;
+  images[i++] = &st->left_front;
+  images[i++] = &st->right_front;
+  images[i++] = &st->front;
+  images[i++] = &st->down;
 
-  static char **bits[] = {
-    nose_l1_xpm, nose_l2_xpm, nose_r1_xpm, nose_r2_xpm,
-    nose_f2_xpm, nose_f3_xpm, nose_f1_xpm, nose_f4_xpm
-  };
+#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
 
+  i = 0;
+  bits[i++] = nose_l1_xpm;
+  bits[i++] = nose_l2_xpm;
+  bits[i++] = nose_r1_xpm;
+  bits[i++] = nose_r2_xpm;
+  bits[i++] = nose_f2_xpm;
+  bits[i++] = nose_f3_xpm;
+  bits[i++] = nose_f1_xpm;
+  bits[i++] = nose_f4_xpm;
 
   for (i = 0; i < sizeof (images) / sizeof(*images); i++)
     {
-      Pixmap pixmap = xpm_data_to_pixmap (dpy, window, bits[i],
+      Pixmap pixmap = xpm_data_to_pixmap (st->dpy, st->window, bits[i],
                                           0, 0, 0);
       if (!pixmap)
        {
@@ -103,14 +143,19 @@ init_images (void)
       *images[i] = pixmap;
     }
 #else
-  static unsigned char *bits[] = {
-    nose_l1_bits, nose_l2_bits, nose_r1_bits, nose_r2_bits,
-    nose_f2_bits, nose_f3_bits, nose_f1_bits, nose_f4_bits
-  };
+  i = 0;
+  bits[i++] = nose_l1_bits;
+  bits[i++] = nose_l2_bits;
+  bits[i++] = nose_r1_bits;
+  bits[i++] = nose_r2_bits;
+  bits[i++] = nose_f2_bits;
+  bits[i++] = nose_f3_bits;
+  bits[i++] = nose_f1_bits;
+  bits[i++] = nose_f4_bits;
 
   for (i = 0; i < sizeof (images) / sizeof(*images); i++)
     if (!(*images[i] =
-         XCreatePixmapFromBitmapData(dpy, window,
+         XCreatePixmapFromBitmapData(st->dpy, st->window,
                                      (char *) bits[i], 64, 64, 1, 0, 1)))
       {
        fprintf (stderr, "%s: Can't load nose images\n", progname);
@@ -128,78 +173,75 @@ init_images (void)
 #define Y_INCR 2
 
 static void
-move (void)
+move (struct state *st)
 {
-    static int      length,
-                    dir;
-
-    if (!length)
+    if (!st->move_length)
     {
        register int    tries = 0;
-       dir = 0;
-       if ((random() & 1) && think())
+       st->move_dir = 0;
+       if ((random() & 1) && think(st))
        {
-           talk(0);            /* sets timeout to itself */
+           talk(st, 0);                /* sets timeout to itself */
            return;
        }
-       if (!(random() % 3) && (interval = look()))
+       if (!(random() % 3) && (st->interval = look(st)))
        {
-           next_fn = move;
+           st->next_fn = move;
            return;
        }
-       interval = 20 + random() % 100;
+       st->interval = 20 + random() % 100;
        do
        {
            if (!tries)
-               length = Width / 100 + random() % 90, tries = 8;
+               st->move_length = st->Width / 100 + random() % 90, tries = 8;
            else
                tries--;
            switch (random() % 8)
            {
            case 0:
-               if (x - X_INCR * length >= 5)
-                   dir = LEFT;
+               if (st->x - X_INCR * st->move_length >= 5)
+                   st->move_dir = LEFT;
                break;
            case 1:
-               if (x + X_INCR * length <= Width - 70)
-                   dir = RIGHT;
+               if (st->x + X_INCR * st->move_length <= st->Width - 70)
+                   st->move_dir = RIGHT;
                break;
            case 2:
-               if (y - (Y_INCR * length) >= 5)
-                   dir = UP, interval = 40;
+               if (st->y - (Y_INCR * st->move_length) >= 5)
+                   st->move_dir = UP, st->interval = 40;
                break;
            case 3:
-               if (y + Y_INCR * length <= Height - 70)
-                   dir = DOWN, interval = 20;
+               if (st->y + Y_INCR * st->move_length <= st->Height - 70)
+                   st->move_dir = DOWN, st->interval = 20;
                break;
            case 4:
-               if (x - X_INCR * length >= 5 && y - (Y_INCR * length) >= 5)
-                   dir = (LEFT | UP);
+               if (st->x - X_INCR * st->move_length >= 5 && st->y - (Y_INCR * st->move_length) >= 5)
+                   st->move_dir = (LEFT | UP);
                break;
            case 5:
-               if (x + X_INCR * length <= Width - 70 &&
-                   y - Y_INCR * length >= 5)
-                   dir = (RIGHT | UP);
+               if (st->x + X_INCR * st->move_length <= st->Width - 70 &&
+                   st->y - Y_INCR * st->move_length >= 5)
+                   st->move_dir = (RIGHT | UP);
                break;
            case 6:
-               if (x - X_INCR * length >= 5 &&
-                   y + Y_INCR * length <= Height - 70)
-                   dir = (LEFT | DOWN);
+               if (st->x - X_INCR * st->move_length >= 5 &&
+                   st->y + Y_INCR * st->move_length <= st->Height - 70)
+                   st->move_dir = (LEFT | DOWN);
                break;
            case 7:
-               if (x + X_INCR * length <= Width - 70 &&
-                   y + Y_INCR * length <= Height - 70)
-                   dir = (RIGHT | DOWN);
+               if (st->x + X_INCR * st->move_length <= st->Width - 70 &&
+                   st->y + Y_INCR * st->move_length <= st->Height - 70)
+                   st->move_dir = (RIGHT | DOWN);
                break;
            default:
                /* No Defaults */
                break;
            }
-       } while (!dir);
+       } while (!st->move_dir);
     }
-    walk(dir);
-    --length;
-    next_fn = move;
+    walk(st, st->move_dir);
+    --st->move_length;
+    st->next_fn = move;
 }
 
 #ifdef HAVE_XPM
@@ -211,82 +253,76 @@ move (void)
 #endif
 
 static void
-walk(int dir)
+walk (struct state *st, int dir)
 {
     register int    incr = 0;
-    static int      lastdir;
-    static int      up = 1;
-    static Pixmap   frame;
 
     if (dir & (LEFT | RIGHT))
-    {                          /* left/right movement (mabye up/down too) */
-       up = -up;               /* bouncing effect (even if hit a wall) */
+    {                          /* left/right movement (mabye up/st->down too) */
+       st->walk_up = -st->walk_up;             /* bouncing effect (even if hit a wall) */
        if (dir & LEFT)
        {
            incr = X_INCR;
-           frame = (up < 0) ? left1 : left2;
+           st->walk_frame = (st->walk_up < 0) ? st->left1 : st->left2;
        }
        else
        {
            incr = -X_INCR;
-           frame = (up < 0) ? right1 : right2;
+           st->walk_frame = (st->walk_up < 0) ? st->right1 : st->right2;
        }
-       if ((lastdir == FRONT || lastdir == DOWN) && dir & UP)
+       if ((st->walk_lastdir == FRONT || st->walk_lastdir == DOWN) && dir & UP)
        {
 
            /*
             * workaround silly bug that leaves screen dust when guy is
-            * facing forward or down and moves up-left/right.
+            * facing forward or st->down and moves up-left/right.
             */
-           COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y);
-           XFlush(dpy);
+           COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
        }
        /* note that maybe neither UP nor DOWN is set! */
-       if (dir & UP && y > Y_INCR)
-           y -= Y_INCR;
-       else if (dir & DOWN && y < Height - 64)
-           y += Y_INCR;
+       if (dir & UP && st->y > Y_INCR)
+           st->y -= Y_INCR;
+       else if (dir & DOWN && st->y < st->Height - 64)
+           st->y += Y_INCR;
     }
-    /* Explicit up/down movement only (no left/right) */
+    /* Explicit up/st->down movement only (no left/right) */
     else if (dir == UP)
-       COPY(dpy, front, window, fg_gc, 0, 0, 64, 64, x, y -= Y_INCR);
+       COPY(st->dpy, st->front, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y -= Y_INCR);
     else if (dir == DOWN)
-       COPY(dpy, down, window, fg_gc, 0, 0, 64, 64, x, y += Y_INCR);
-    else if (dir == FRONT && frame != front)
+       COPY(st->dpy, st->down, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y += Y_INCR);
+    else if (dir == FRONT && st->walk_frame != st->front)
     {
-       if (up > 0)
-           up = -up;
-       if (lastdir & LEFT)
-           frame = left_front;
-       else if (lastdir & RIGHT)
-           frame = right_front;
+       if (st->walk_up > 0)
+           st->walk_up = -st->walk_up;
+       if (st->walk_lastdir & LEFT)
+           st->walk_frame = st->left_front;
+       else if (st->walk_lastdir & RIGHT)
+           st->walk_frame = st->right_front;
        else
-           frame = front;
-       COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y);
+           st->walk_frame = st->front;
+       COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
     }
     if (dir & LEFT)
        while (--incr >= 0)
        {
-           COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, --x, y + up);
-           XFlush(dpy);
+           COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, --st->x, st->y + st->walk_up);
        }
     else if (dir & RIGHT)
        while (++incr <= 0)
        {
-           COPY(dpy, frame, window, fg_gc, 0, 0, 64, 64, ++x, y + up);
-           XFlush(dpy);
+           COPY(st->dpy, st->walk_frame, st->window, st->fg_gc, 0, 0, 64, 64, ++st->x, st->y + st->walk_up);
        }
-    lastdir = dir;
+    st->walk_lastdir = dir;
 }
 
 static int
-think (void)
+think (struct state *st)
 {
     if (random() & 1)
-       walk(FRONT);
+       walk(st, FRONT);
     if (random() & 1)
     {
-      words = get_words();
+      st->words = get_words(st);
       return 1;
     }
     return 0;
@@ -299,59 +335,49 @@ think (void)
 
 
 static void
-talk(int force_erase)
+talk (struct state *st, int force_erase)
 {
     int             width = 0,
                     height,
                     Z,
                     total = 0;
-    static int      X,
-                    Y,
-                    talking;
-    static struct
-    {
-       int             x,
-                       y,
-                       width,
-                       height;
-    }               s_rect;
     register char  *p,
                    *p2;
     char            buf[BUFSIZ],
                     args[MAXLINES][256];
 
     /* clear what we've written */
-    if (talking || force_erase)
+    if (st->talking || force_erase)
     {
-       if (!talking)
+       if (!st->talking)
            return;
-       XFillRectangle(dpy, window, bg_gc, s_rect.x - 5, s_rect.y - 5,
-                      s_rect.width + 10, s_rect.height + 10);
-       talking = 0;
+       XFillRectangle(st->dpy, st->window, st->bg_gc, st->s_rect.x - 5, st->s_rect.y - 5,
+                      st->s_rect.width + 10, st->s_rect.height + 10);
+       st->talking = 0;
        if (!force_erase)
-         next_fn = move;
-       interval = 0;
+         st->next_fn = move;
+       st->interval = 0;
        {
-         /* might as well check the window for size changes now... */
+         /* might as well check the st->window for size changes now... */
          XWindowAttributes xgwa;
-         XGetWindowAttributes (dpy, window, &xgwa);
-         Width = xgwa.width + 2;
-         Height = xgwa.height + 2;
+         XGetWindowAttributes (st->dpy, st->window, &xgwa);
+         st->Width = xgwa.width + 2;
+         st->Height = xgwa.height + 2;
        }
        return;
     }
-    talking = 1;
-    walk(FRONT);
-    p = strcpy(buf, words);
+    st->talking = 1;
+    walk(st, FRONT);
+    p = strcpy(buf, st->words);
 
     for (p2 = p; *p2; p2++)
       if (*p2 == '\t') *p2 = ' ';
 
     if (!(p2 = strchr(p, '\n')) || !p2[1])
       {
-       total = strlen (words);
-       strcpy (args[0], words);
-       width = XTextWidth(font, words, total);
+       total = strlen (st->words);
+       strcpy (args[0], st->words);
+       width = XTextWidth(st->font, st->words, total);
        height = 0;
       }
     else
@@ -360,7 +386,7 @@ talk(int force_erase)
        {
          int             w;
          *p2 = 0;
-         if ((w = XTextWidth(font, p, p2 - p)) > width)
+         if ((w = XTextWidth(st->font, p, p2 - p)) > width)
            width = w;
          total += p2 - p;      /* total chars; count to determine reading
                                 * time */
@@ -380,146 +406,145 @@ talk(int force_erase)
      * Figure out the height and width in pixels (height, width) extend the
      * new box by 15 pixels on the sides (30 total) top and bottom.
      */
-    s_rect.width = width + 30;
-    s_rect.height = height * font_height(font) + 30;
-    if (x - s_rect.width - 10 < 5)
-       s_rect.x = 5;
-    else if ((s_rect.x = x + 32 - (s_rect.width + 15) / 2)
-            + s_rect.width + 15 > Width - 5)
-       s_rect.x = Width - 15 - s_rect.width;
-    if (y - s_rect.height - 10 < 5)
-       s_rect.y = y + 64 + 5;
+    st->s_rect.width = width + 30;
+    st->s_rect.height = height * font_height(st->font) + 30;
+    if (st->x - st->s_rect.width - 10 < 5)
+       st->s_rect.x = 5;
+    else if ((st->s_rect.x = st->x + 32 - (st->s_rect.width + 15) / 2)
+            + st->s_rect.width + 15 > st->Width - 5)
+       st->s_rect.x = st->Width - 15 - st->s_rect.width;
+    if (st->y - st->s_rect.height - 10 < 5)
+       st->s_rect.y = st->y + 64 + 5;
     else
-       s_rect.y = y - 5 - s_rect.height;
+       st->s_rect.y = st->y - 5 - st->s_rect.height;
 
-    XFillRectangle(dpy, window, text_bg_gc,
-        s_rect.x, s_rect.y, s_rect.width, s_rect.height);
+    XFillRectangle(st->dpy, st->window, st->text_bg_gc,
+        st->s_rect.x, st->s_rect.y, st->s_rect.width, st->s_rect.height);
 
     /* make a box that's 5 pixels thick. Then add a thin box inside it */
-    XSetLineAttributes(dpy, text_fg_gc, 5, 0, 0, 0);
-    XDrawRectangle(dpy, window, text_fg_gc,
-                  s_rect.x, s_rect.y, s_rect.width - 1, s_rect.height - 1);
-    XSetLineAttributes(dpy, text_fg_gc, 0, 0, 0, 0);
-    XDrawRectangle(dpy, window, text_fg_gc,
-        s_rect.x + 7, s_rect.y + 7, s_rect.width - 15, s_rect.height - 15);
+    XSetLineAttributes(st->dpy, st->text_fg_gc, 5, 0, 0, 0);
+    XDrawRectangle(st->dpy, st->window, st->text_fg_gc,
+                  st->s_rect.x, st->s_rect.y, st->s_rect.width - 1, st->s_rect.height - 1);
+    XSetLineAttributes(st->dpy, st->text_fg_gc, 0, 0, 0, 0);
+    XDrawRectangle(st->dpy, st->window, st->text_fg_gc,
+        st->s_rect.x + 7, st->s_rect.y + 7, st->s_rect.width - 15, st->s_rect.height - 15);
 
-    X = 15;
-    Y = 15 + font_height(font);
+    st->X = 15;
+    st->Y = 15 + font_height(st->font);
 
     /* now print each string in reverse order (start at bottom of box) */
     for (Z = 0; Z < height; Z++)
     {
-       XDrawString(dpy, window, text_fg_gc, s_rect.x + X, s_rect.y + Y,
-                   args[Z], strlen(args[Z]));
-       Y += font_height(font);
+        int L = strlen(args[Z]);
+        if (args[Z][L-1] == '\r' || args[Z][L-1] == '\n')
+          args[Z][--L] = 0;
+       XDrawString(st->dpy, st->window, st->text_fg_gc, st->s_rect.x + st->X, st->s_rect.y + st->Y,
+                   args[Z], L);
+       st->Y += font_height(st->font);
     }
-    interval = (total / 15) * 1000;
-    if (interval < 2000) interval = 2000;
-    next_fn = talk_1;
+    st->interval = (total / 15) * 1000;
+    if (st->interval < 2000) st->interval = 2000;
+    st->next_fn = talk_1;
 }
 
-static void talk_1 (void) 
+static void
+talk_1 (struct state *st) 
 {
-  talk(0);
+  talk(st, 0);
 }
 
 
 static unsigned long
-look (void)
+look (struct state *st)
 {
     if (random() % 3)
     {
-       COPY(dpy, (random() & 1) ? down : front, window, fg_gc,
-            0, 0, 64, 64, x, y);
+       COPY(st->dpy, (random() & 1) ? st->down : st->front, st->window, st->fg_gc,
+            0, 0, 64, 64, st->x, st->y);
        return 1000L;
     }
     if (!(random() % 5))
        return 0;
     if (random() % 3)
     {
-       COPY(dpy, (random() & 1) ? left_front : right_front,
-            window, fg_gc, 0, 0, 64, 64, x, y);
+       COPY(st->dpy, (random() & 1) ? st->left_front : st->right_front,
+            st->window, st->fg_gc, 0, 0, 64, 64, st->x, st->y);
        return 1000L;
     }
     if (!(random() % 5))
        return 0;
-    COPY(dpy, (random() & 1) ? left1 : right1, window, fg_gc,
-        0, 0, 64, 64, x, y);
+    COPY(st->dpy, (random() & 1) ? st->left1 : st->right1, st->window, st->fg_gc,
+        0, 0, 64, 64, st->x, st->y);
     return 1000L;
 }
 
 
 static void
-init_words (void)
+init_words (struct state *st)
 {
-  program = get_string_resource ("program", "Program");
-  filename = get_string_resource ("filename", "Filename");
-  text = get_string_resource ("text", "Text");
+  st->program = get_string_resource (st->dpy, "program", "Program");
 
-  if (program) /* get stderr on stdout, so it shows up on the window */
+  if (st->program)     /* get stderr on stdout, so it shows up on the window */
     {
-      orig_program = program;
-      program = (char *) malloc (strlen (program) + 10);
-      strcpy (program, "( ");
-      strcat (program, orig_program);
-      strcat (program, " ) 2>&1");
+      st->orig_program = st->program;
+      st->program = (char *) malloc (strlen (st->program) + 10);
+      strcpy (st->program, "( ");
+      strcat (st->program, st->orig_program);
+      strcat (st->program, " ) 2>&1");
     }
 
-  words = get_words(); 
+  st->words = get_words(st);   
 }
 
-static int first_time = 1;
-
 static char *
-get_words (void)
+get_words (struct state *st)
 {
     FILE           *pp;
-    static char     buf[BUFSIZ];
-    register char  *p = buf;
+    register char  *p = st->word_buf;
 
-    buf[0] = '\0';
+    st->word_buf[0] = '\0';
 
-       if ((pp = popen(program, "r")))
+       if ((pp = popen(st->program, "r")))
        {
-           while (fgets(p, sizeof(buf) - strlen(buf), pp))
+           while (fgets(p, sizeof(st->word_buf) - strlen(st->word_buf), pp))
            {
-               if (strlen(buf) + 1 < sizeof(buf))
-                   p = buf + strlen(buf);
+               if (strlen(st->word_buf) + 1 < sizeof(st->word_buf))
+                   p = st->word_buf + strlen(st->word_buf);
                else
                    break;
            }
            (void) pclose(pp);
-           if (! buf[0])
-             sprintf (buf, "\"%s\" produced no output!", orig_program);
-           else if (!first_time &&
-                    (strstr (buf, ": not found") ||
-                     strstr (buf, ": Not found") ||
-                      strstr (buf, ": command not found") ||
-                      strstr (buf, ": Command not found")))
+           if (! st->word_buf[0])
+             sprintf (st->word_buf, "\"%s\" produced no output!", st->orig_program);
+           else if (!st->first_time &&
+                    (strstr (st->word_buf, ": not found") ||
+                     strstr (st->word_buf, ": Not found") ||
+                      strstr (st->word_buf, ": command not found") ||
+                      strstr (st->word_buf, ": Command not found")))
              switch (random () % 20)
                {
-               case 1: strcat (buf, "( Get with the program, bub. )\n");
+               case 1: strcat (st->word_buf, "( Get with the st->program, bub. )\n");
                  break;
-               case 2: strcat (buf,
+               case 2: strcat (st->word_buf,
                  "( I blow my nose at you, you silly person! ) \n"); break;
-               case 3: strcat (buf,
+               case 3: strcat (st->word_buf,
                  "\nThe resource you want to\nset is `noseguy.program'\n");
                  break;
                case 4:
-                 strcat(buf,"\nHelp!!  Help!!\nAAAAAAGGGGHHH!!  \n\n"); break;
-               case 5: strcpy (buf, "You have new mail.\n"); break;
+                 strcat(st->word_buf,"\nHelp!!  Help!!\nAAAAAAGGGGHHH!!  \n\n"); break;
+               case 5: strcpy (st->word_buf, "You have new mail.\n"); break;
                case 6:
-                 strcat(buf,"( Hello?  Are you paying attention? )\n");break;
+                 strcat(st->word_buf,"( Hello?  Are you paying attention? )\n");break;
                case 7:
-                 strcat (buf, "sh: what kind of fool do you take me for? \n");
+                 strcat (st->word_buf, "sh: what kind of fool do you take me for? \n");
                  break;
                }
-           first_time = 0;
-           p = buf;
+           st->first_time = 0;
+           p = st->word_buf;
        }
        else
        {
-           perror(program);
+           perror(st->program);
        }
 
     return p;
@@ -527,21 +552,18 @@ get_words (void)
 
 
 \f
-char *progclass = "Noseguy";
-
-char *defaults [] = {
-  ".background:         black",
-  ".foreground:         gray80",
+static const char *noseguy_defaults [] = {
+  ".background:            black",
+  ".foreground:            #CCCCCC",
+  "*textForeground: black",
+  "*textBackground: #CCCCCC",
   "*program:    xscreensaver-text --cols 40 | head -n15",
-  "noseguy.font: -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*",
+  ".font:       -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*",
   0
 };
 
-XrmOptionDescRec options [] = {
-  { "-mode",           ".mode",                XrmoptionSepArg, 0 },
+static XrmOptionDescRec noseguy_options [] = {
   { "-program",                ".program",             XrmoptionSepArg, 0 },
-  { "-text",           ".text",                XrmoptionSepArg, 0 },
-  { "-filename",       ".filename",            XrmoptionSepArg, 0 },
   { "-font",           ".font",                XrmoptionSepArg, 0 },
   { "-text-foreground",        ".textForeground",      XrmoptionSepArg, 0 },
   { "-text-background",        ".textBackground",      XrmoptionSepArg, 0 },
@@ -549,88 +571,96 @@ XrmOptionDescRec options [] = {
 };
 
 
-static void
+static void *
 noseguy_init (Display *d, Window w)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   unsigned long fg, bg, text_fg, text_bg;
   XWindowAttributes xgwa;
   Colormap cmap;
-  char *fontname = get_string_resource ("font", "Font");
-  char **list;
-  int foo, i;
+  char *fontname;
   XGCValues gcvalues;
-  dpy = d;
-  window = w;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  Width = xgwa.width + 2;
-  Height = xgwa.height + 2;
+  st->dpy = d;
+  st->window = w;
+  st->first_time = 1;
+
+  fontname = get_string_resource (st->dpy, "font", "Font");
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
+  st->Width = xgwa.width + 2;
+  st->Height = xgwa.height + 2;
   cmap = xgwa.colormap;
 
-  init_words();
-  init_images();
+  init_words(st);
+  init_images(st);
 
-  if (!fontname || !(font = XLoadQueryFont(dpy, fontname)))
-    {
-       list = XListFonts(dpy, FONT_NAME, 32767, &foo);
-       for (i = 0; i < foo; i++)
-           if ((font = XLoadQueryFont(dpy, list[i])))
-               break;
-       if (!font)
-         {
-           fprintf (stderr, "%s: Can't find a large font.", progname);
-           exit (1);
-         }
-       XFreeFontNames(list);
-    }
+  if (!fontname || !*fontname)
+    fprintf (stderr, "%s: no font specified.\n", progname);
+  st->font = XLoadQueryFont(st->dpy, fontname);
+  if (!st->font)
+    fprintf (stderr, "%s: could not load font %s.\n", progname, fontname);
 
-  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
-  bg = get_pixel_resource ("background", "Background", dpy, cmap);
-  text_fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap);
-  text_bg = get_pixel_resource ("textBackground", "Background", dpy, cmap);
+  fg = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground");
+  bg = get_pixel_resource (st->dpy, cmap, "background", "Background");
+  text_fg = get_pixel_resource (st->dpy, cmap, "textForeground", "Foreground");
+  text_bg = get_pixel_resource (st->dpy, cmap, "textBackground", "Background");
   /* notice when unspecified */
-  if (! get_string_resource ("textForeground", "Foreground"))
+  if (! get_string_resource (st->dpy, "textForeground", "Foreground"))
     text_fg = bg;
-  if (! get_string_resource ("textBackground", "Background"))
+  if (! get_string_resource (st->dpy, "textBackground", "Background"))
     text_bg = fg;
 
-  gcvalues.font = font->fid;
-  gcvalues.graphics_exposures = False;
+  gcvalues.font = st->font->fid;
   gcvalues.foreground = fg;
   gcvalues.background = bg;
-  fg_gc = XCreateGC (dpy, window,
-                    GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+  st->fg_gc = XCreateGC (st->dpy, st->window,
+                         GCForeground|GCBackground|GCFont,
                     &gcvalues);
   gcvalues.foreground = bg;
   gcvalues.background = fg;
-  bg_gc = XCreateGC (dpy, window,
-                    GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+  st->bg_gc = XCreateGC (st->dpy, st->window,
+                         GCForeground|GCBackground|GCFont,
                     &gcvalues);
   gcvalues.foreground = text_fg;
   gcvalues.background = text_bg;
-  text_fg_gc = XCreateGC (dpy, window,
-                         GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+  st->text_fg_gc = XCreateGC (st->dpy, st->window,
+                              GCForeground|GCBackground|GCFont,
                          &gcvalues);
   gcvalues.foreground = text_bg;
   gcvalues.background = text_fg;
-  text_bg_gc = XCreateGC (dpy, window,
-                         GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+  st->text_bg_gc = XCreateGC (st->dpy, st->window, 
+                              GCForeground|GCBackground|GCFont,
                          &gcvalues);
-  x = Width / 2;
-  y = Height / 2;
-  state = IS_MOVING;
+  st->x = st->Width / 2;
+  st->y = st->Height / 2;
+  st->state = IS_MOVING;
+  st->next_fn = move;
+  st->walk_up = 1;
+  return st;
 }
      
-void
-screenhack (Display *d, Window w)
+static unsigned long
+noseguy_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  st->next_fn(st);
+  return (st->interval * 1000);
+}
+
+static void
+noseguy_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+noseguy_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
+}
+
+static void
+noseguy_free (Display *dpy, Window window, void *closure)
 {
-  noseguy_init (d, w);
-  next_fn = move;
-  while (1)
-    {
-      next_fn();
-      XSync (dpy, False);
-      screenhack_handle_events (dpy);
-      usleep (interval * 1000);
-    }
 }
 
+XSCREENSAVER_MODULE ("NoseGuy", noseguy)